2011-04-07 17 views
10

Tôi không hiểu tại sao chúng ta phải gọi phương thức setSelector trên NSInvocation đối tượng khi thông tin đó đã được chuyển qua invocationWithMethodSignature.Mục đích của phương thức setSelector trên lớp NSInvocation là gì?

Để tạo một đối tượng NSInvocation chúng ta làm như sau:

SEL someSelector; 
NSMethodSignature *signature; 
NSInvocation *invocation; 

someSelector = @selector(sayHelloWithString:); 

//Here we use the selector to create the signature 
signature = [SomeObject instanceMethodSignatureForSelector:someSelector]; 
invocation = [NSInvocation invocationWithMethodSignature:signature]; 

//Here, we again set the same selector 
[invocation setSelector:someSelector]; 
[invocation setTarget:someObjectInstance]; 
[invocation setArgument:@"Loving C" atIndex:2]; 

Chú ý rằng chúng tôi thông qua bộ chọn để [SomeObject instanceMethodSignatureForSelector: someSelector]; và một lần nữa để [invocation setSelector:someSelector];.

Có điều gì tôi thiếu không?

+1

+1 - Tốt khi xem câu hỏi ở đây chưa được hỏi (và trả lời) một triệu lần rồi, và không được viết bằng biệt ngữ thư không thể giải mã được. :-) –

+0

Một điểm nhỏ: 'signature = [SomeObject instanceMethodSignatureForSelector: someSelector];' phải là 'signature = [[SomeObject class] instanceMethodSignatureForSelector: someSelector]; hoặc chữ ký = [SomeObject methodSignatureForSelector: someSelector]; ' – Brynjar

Trả lời

8

Chữ ký không phải là bộ chọn. Bộ chọn là tên của một tin nhắn. Chữ ký xác định các tham số và giá trị trả về. Bạn có thể có nhiều bộ chọn có cùng chữ ký và ngược lại. Nếu bạn nhìn vào NSMethodSignature, bạn sẽ thấy rằng không có phương thức -selector; chữ ký không mang theo một bộ chọn cụ thể.

Hãy xem xét những điều sau

- (void)setLocation:(CGFloat)aLocation; 
- (void)setLocation:(MyLocation*)aLocation; 

Họ có cùng một selector @selector(setLocation:), nhưng chữ ký khác nhau.

- (void)setX:(CGFloat)x; 
- (void)setY:(CGFloat)y; 

Chúng có cùng chữ ký, nhưng các bộ chọn khác nhau.

Selectors từ Ngôn ngữ lập trình ObjC có thể là tài liệu tham khảo hữu ích để hiểu điều này.

+0

Trong khi tôi nhận được những gì bạn đang nói, có vẻ là một chút dư thừa trong ngôn ngữ. Tôi đang thiết lập bộ chọn hai lần (một lần trong chữ ký, và một lần nữa trên thể hiện yêu cầu). Cá nhân tôi (IMHO) nghĩ rằng nó sẽ hiệu quả hơn để lấy được bộ chọn (mà trong trường hợp của tôi đã được định nghĩa trong 'someSelector') từ chữ ký. – haroldcampbell

+0

Bạn không thể lấy được bộ chọn từ chữ ký. Bạn có thể lấy được một chữ ký từ một đích và một bộ chọn bằng cách hỏi đích (hãy nhớ rằng, các phương thức và lớp mới có thể được tạo ra trong thời gian chạy; bạn không thể xác định được điều này trong thời gian biên dịch).Bạn nói đúng rằng có thể có phương thức '+ invocationWithTarget: selector: arguments:' (nhóm của tôi có một danh mục bổ sung một cái gì đó tương tự). Nó sẽ không hiệu quả hơn vì nó chỉ gọi mã mà bạn đang gọi, nhưng nó sẽ thuận tiện hơn một chút. –

3

Chữ ký phương thức chỉ xác định loại trả về, số và loại đối số. Nó không bao gồm bất cứ điều gì về tên bộ chọn. Ví dụ, tất cả các phương pháp có chữ ký giống nhau, mặc dù có bộ chọn khác nhau:

-(void) foo:(NSString*)fooString; 
-(void) bar:(NSString*)barString; 
-(void) baz:(NSString*)bazString; 
0

Đây là loại một phụ câu trả lời, nhưng thực tế là bạn có thể làm những điều sau đây đã giúp tôi hiểu rõ hơn về sự tách biệt giữa phương pháp chữ ký và bộ chọn.

Mã này nằm trong một View Controller

NSMethodSignature *sig = nil; 
sig = [[self class] instanceMethodSignatureForSelector:@selector(viewDidAppear:)]; 
NSInvocation *myInvocation = nil; 
myInvocation = [NSInvocation invocationWithMethodSignature:sig]; 

[myInvocation setTarget:_somePopoverController]; 
[myInvocation setSelector:@selector(dismissPopoverAnimated:)]; 
BOOL animate = YES; 
[myInvocation setArgument:&animate atIndex:2]; 
[myInvocation invoke]; 

Kể từ UIViewController của viewDidAppear: và dismissPopoverAnimated UIPopoverController, thì hai người mất một đối số BOOL và trở về bãi bỏ, bạn có thể tạo chữ ký phương pháp sử dụng một selector, nhưng gửi invocation khác.