2010-09-12 48 views
57
- (void)someMethod 
{ 
    if ([delegate respondsToSelector:@selector(operationShouldProceed)]) 
    { 
     if ([delegate operationShouldProceed]) 
     { 
      // do something appropriate 
     } 
    } 
} 

Các documentation nói:khi sử dụng respondsToSelector trong Objective-C

Các biện pháp phòng ngừa là cần thiết chỉ cho các phương pháp tùy chọn trong một giao thức chính quy hoặc các phương pháp của một giao thức không chính thức

gì nghĩa là? Nếu tôi sử dụng giao thức chính thức, tôi chỉ có thể sử dụng [delegate myMethod]?

Trả lời

74

Bạn sử dụng nó khá nhiều chỉ khi bạn nghĩ rằng bạn cần: để kiểm tra xem một đối tượng có thực hiện phương thức bạn sắp gọi hay không. Thông thường việc này được thực hiện khi bạn có phương thức tùy chọn hoặc giao thức không chính thức.

Tôi chỉ từng sử dụng respondsToSelector khi tôi viết mã phải giao tiếp với đối tượng đại biểu.

if ([self.delegate respondsToSelector:@selector(engineDidStartRunning:)]) { 
     [self.delegate engineDidStartRunning:self]; 
    } 

Đôi khi bạn muốn sử dụng respondsToSelector trên bất kỳ phương thức trả về và id hoặc generic NSObject nơi bạn không chắc chắn những gì lớp của đối tượng quay trở lại được.

+0

cảm ơn. Giờ thì tôi đã hiểu.Tôi nhận thấy bạn sử dụng self.delegate, đó là một tài sản. Tôi chỉ sử dụng một biến dụ: id delegate. có gì khác biệt? Im học tập mục tiêu-c. cảm ơn một lần nữa – Taho

+2

'self.delegate' giống hệt như gọi' [self delegate] '. Trong mã của tôi không có sự khác biệt giữa '[self.delegate someMethod]' và '[_delegate someMethod]', nhưng tôi có xu hướng sử dụng dấu chấm cú pháp vì nó giữ nó thẳng trong tâm trí của tôi mà biến là địa phương để các phương pháp tôi đang ở và đó là các biến mẫu. – kubi

+0

Nếu bạn chỉ mới bắt đầu, nó sẽ có giá trị thời gian của bạn để đọc hướng dẫn của Apple để Obj-C. http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocProperties.html%23//apple_ref/doc/uid/TP30001163-CH17 – kubi

45

Chỉ cần thêm vào những gì @kubi nói, một lần khác tôi sử dụng nó là khi một phương thức được thêm vào một lớp đã tồn tại trong một phiên bản mới hơn của khung công tác, nhưng tôi vẫn cần phải tương thích ngược. Ví dụ:

if ([myObject respondsToSelector:@selector(doAwesomeNewThing)]) { 
    [myObject doAwesomeNewThing]; 
} else { 
    [self doOldWorkaroundHackWithObject:myObject]; 
} 
2

Cũ câu hỏi, nhưng tôi đã học được rất cautios với việc sử dụng công cụ như addTarget: @selector (fu :) vì tên phương pháp không được chọn cũng không có trong refactoring bởi Xcode. Điều này đã gây ra cho tôi khá nhiều rắc rối rồi. Vì vậy, bây giờ tôi đã làm cho nó một habbit luôn nhúng công cụ như addTarget hoặc addObserver trong một respondsToSelector-Kiểm tra như sau:

if([self respondsToSelector:@selector(buttonClicked:)]){ 
    [self.button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside]; 
}else{ 
    DebugLog(@"Warning - a class or delegate did not respond to selector in class %@", self); 
} 

Tôi biết nó không phải là siêu thanh lịch, nhưng tôi thà thêm một số mã boilerplate hơn có một bất ngờ sự cố của ứng dụng của tôi trong App Store.

+0

Tôi nghĩ rằng "methodName:" bây giờ được kiểm tra trong các câu lệnh như @selector (methodName :) trong xCode bây giờ không phải là chúng? – Grezzo

+1

@Grezzo - XCode sẽ chỉ kiểm tra rằng bộ chọn tồn tại ở đâu đó trong mục tiêu của bạn. Vì vậy, ví dụ nếu bạn đã viết '@selector (ngày)' thay vì '@selector (data)' XCode sẽ không cảnh báo bạn vì bộ chọn 'date' tồn tại trên' NSDateComponents'. – Robert

11

Vì kubi được đề cập respondsToSelector thường được sử dụng khi bạn có một thể hiện của một phương thức phù hợp với giao thức.

// Extend from the NSObject protocol so it is safe to call `respondsToSelector` 
@protocol MyProtocol <NSObject> 

// @required by default 
- (void) requiredMethod; 

@optional 

- (void)optionalMethod; 

@end 

Cho và thể hiện giao thức này, chúng tôi có thể gọi một cách an toàn mọi phương thức được yêu cầu.

id <MyProtocol> myObject = ... 
[myObject requiredMethod]; 

Tuy nhiên, phương pháp tùy chọn có thể hoặc không thể được triển khai, vì vậy bạn cần kiểm tra khi chạy.

if ([myObject respondsToSelector:@selector(optionalMethod)]) 
{ 
    [myObject optionalMethod]; 
} 

Làm như vậy sẽ ngăn ngừa sự cố với bộ chọn không được công nhận.


Ngoài ra, lý do tại sao bạn nên tuyên bố các giao thức như một phần mở rộng của NSObjects, ví dụ:

@protocol MyProtocol <NSObject> 

Là bởi vì các giao thức NSObject tuyên bố chọn respondsToSelector:. Nếu không XCode sẽ nghĩ rằng không an toàn để gọi nó là gì.

+0

Tôi chỉ quên thêm giải quyết được vấn đề của tôi –

Các vấn đề liên quan