2010-02-19 25 views
25

Tôi đã sử dụng @selector hôm nay lần đầu tiên và không thể tìm ra cách thực hiện những điều sau đây? Làm thế nào bạn sẽ viết @selector nếu bạn có nhiều hơn một đối số?@selector - Với nhiều đối số?

Không có đối số:

-(void)printText { 
    NSLog(@"Fish"); 
} 

[self performSelector:@selector(printText) withObject:nil afterDelay:0.25]; 

Độc lập luận:

-(void)printText:(NSString *)myText { 
    NSLog(@"Text = %@", myText); 
} 

[self performSelector:@selector(printText:) withObject:@"Cake" afterDelay:0.25]; 

Hai đối số:

-(void)printText:(NSString *)myText andMore:(NSString *)extraText { 
    NSLog(@"Text = %@ and %@", myText, extraText); 
} 

[self performSelector:@selector(printText:andMore:) withObject:@"Cake" withObject:@"Chips"]; 

Nhiều luận cứ: (ví dụ hơn 2)

NSInvocation

+0

cập nhật để phản ánh câu trả lời, cảm ơn vì tất cả sự giúp đỡ, nhiều đánh giá cao. – fuzzygoat

+1

"đối số kép" của bạn không có độ trễ – user102008

Trả lời

35

 

- (id)performSelector:(SEL)aSelector 
      withObject:(id)anObject 
      withObject:(id)anotherObject 

Từ Documentation:

Phương pháp này cũng giống như performSelector: ngoại trừ việc bạn có thể cung cấp hai đối số cho aSelector. aSelector nên xác định một phương thức có thể lấy hai đối số của id loại. Đối với các phương thức có các kiểu đối số và giá trị trả lại khác, hãy sử dụng NSInvocation.

như vậy trong trường hợp của bạn, bạn sẽ sử dụng:

[self performSelector:@selector(printText:andMore:) 
      withObject:@"Cake" 
      withObject:@"More Cake"] 
5
@selector(printText:andMore:) 
+4

cảm ơn bạn, nhưng làm cách nào tôi chỉ định đối số @ "Bánh" và @ "Bánh khác"? – fuzzygoat

4
[self performSelector:@selector(printText:andMore) withObject:@"Cake" withObject:@"More Cake"]; 
+1

Có '-performSelector: withObject: withObject:' và '-performSelector: withObject: afterDelay:', nhưng kết hợp cả hai không tồn tại. – kennytm

+0

Đúng vậy. Tôi đã sao chép/dán và mắc lỗi. Vị trí tốt – pheelicks

1

Như KennyTM chỉ ra, cú pháp selector là

@selector(printText:andMore:) 

Bạn gọi nó với

performSelector:withObject:withObject. 

.. Nếu bạn cần thêm đối số hoặc các loại khác nhau, bạn cần sử dụng NSIvocation

14

Tôi gặp sự cố khi tôi cần sử dụng afterDelay cùng với nhiều đối số cho phương pháp @selector của mình. Dung dịch? Sử dụng hàm bao bọc!

nói đây là chức năng tôi muốn để vượt qua để @selector:

-(void)myFunct:(NSString *)arg1 andArg:(NSString *)arg2 andYetAnotherArg:(NSString *)arg3; 

Rõ ràng, tôi không thể thậm chí sử dụng withObject: withObject: đây, vì vậy, tạo một wrapper!

-(void)myFunctWrapper:(NSArray *)myArgs { 
    [self myFunct:[myArgs objectAtIndex:0] andArg:[myArgs objectAtIndex:1] andYetAnotherArg:[myArgs objectAtIndex:2]]; 
} 

và sử dụng nó bằng cách thực hiện:

NSArray *argArray = [NSArray arrayWithObjects:string1,string2,string3,nil]; 
[self performSelector:@selector(myFunctWrapper:) withObject:argArray afterDelay:1.0]; 

Bằng cách này tôi có thể có nhiều lý lẽ sử dụng bộ chọn với sự chậm trễ.

+1

Những thứ bạn gọi hàm này thực sự được gọi là phương thức. Không chỉ trong mục tiêu-C, nhưng trong tất cả các ngôn ngữ lập trình nghiêm trọng, sự khác biệt này được tạo ra. Để chính xác: ngay khi vật này được gắn vào một vật thể, đó là một phương pháp. Đứng một mình nó được gọi là một chức năng. – Jacque

+0

Cảm ơn thông tin? – aqua

+0

Đối với trường hợp chung tôi có xu hướng sử dụng một từ điển để vượt qua các parms. Bạn không phụ thuộc vào đơn đặt hàng và bạn có thể dễ dàng có các parm tùy chọn, v.v. –

17

Là một thay thế cho NSInvocation khi bạn có nhiều hơn hai tham số, bạn có thể sử dụng NSObject của -methodForSelector: như trong ví dụ sau:

SEL a_selector = ... 
Type1 obj1 = ... 
Type2 obj2 = ... 
Type3 obj3 = ... 
typedef void (*MethodType)(id, SEL, Type1, Type2, Type3); 
MethodType methodToCall; 
methodToCall = (MethodType)[target methodForSelector:a_selector]; 
methodToCall(target, a_selector, obj1, obj_of_type2, obj_of_type3); 
+1

Đây chính xác là những gì tôi đang tìm kiếm. Tôi cần thiết để có thể vượt qua trong các tham số bằng cách tham khảo, và không thể tìm ra cách để làm điều đó với performSelector. Tôi đã tìm ra nó với NSInvocation, nhưng tôi vẫn nhận được lỗi malloc. Điều này đã làm chính xác những gì tôi cần nó để làm. –

2

Xây dựng trên Ben-Uri's answer, có thể được viết theo cách ngắn hơn.

Ví dụ: gọi phương thức UIView- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view thể được thực hiện như sau:

SEL selector = @selector(covertPoint:toView:); 
IMP method = [viewA methodForSelector:selector]; 
CGPoint pointInB = method(viewA, selector, pointInA, viewB); 
+0

Dựa trên bài đăng SO này (http://stackoverflow.com/questions/10952996/why-does-this-code-give-exc-bad-access-using-imp), bạn sẽ gặp phải vấn đề về bộ nhớ khi thực hiện theo cách này nếu bạn có Đã bật ARC. – stuckj

4

Một lựa chọn khác là sử dụng một cú pháp thậm chí ngắn hơn:

#import <objc/message.h> // objc_msgSend 
... 
((void (*)(id, SEL, Type1, Type2, Type3))objc_msgSend)(target, a_selector, obj1, obj_of_type2, obj_of_type3); 
Các vấn đề liên quan