Tôi có hai lớp có thể hoạt động như một đại biểu của một lớp thứ ba và cả hai thực hiện một giao thức chính thức được thực hiện hoàn toàn bằng các phương thức tùy chọn. Một trong các lớp thực hiện mọi thứ trong khi một lớp khác chỉ thực hiện một vài phương thức mà tôi quan tâm. Tuy nhiên, vào thời gian chạy khi tôi có lớp thứ hai hoạt động như ủy nhiệm cho lớp thứ ba, và lớp thứ ba kết thúc lên gọi một trong các phương thức tùy chọn chưa được thực hiện trên đại biểu đó, tôi nhận được lỗi thời gian chạy về cơ bản nói "Mục tiêu không phản hồi điều này bộ chọn tin nhắn. " Tôi nghĩ rằng mục tiêu-c xử lý trường hợp này một cách chính xác, và rằng nó sẽ chỉ làm gì nếu phương pháp đó đã không thực sự được xác định trên lớp. Có thể có một cái gì đó tôi đang mất tích?Tại sao các phương thức giao thức tùy chọn chưa thực hiện gây ra lỗi thời gian chạy khi phương thức đó được gọi trong obj-c?
Trả lời
Khi bạn gọi một phương pháp bắt buộc của đại biểu của bạn, bạn cần phải chắc chắn rằng nó phản ứng với bộ chọn trước khi gọi nó:
if ([delegate respondsToSelector:@selector(optionalMethod)])
[delegate optionalMethod];
phương pháp giao thức bắt buộc chỉ đơn giản có nghĩa là các đối tượng thực hiện các giao thức không nhất thiết phải thực hiện phương pháp được đề cập - callee sau đó hoàn toàn phải kiểm tra xem đối tượng có thực hiện phương thức trước khi gọi hay không (nếu không bạn sẽ gặp sự cố, như bạn đã thấy). Những loại NSObject HOM có thể hữu ích:
@implementation NSObject (Extensions)
- (id)performSelectorIfResponds:(SEL)aSelector
{
if ([self respondsToSelector:aSelector]) {
return [self performSelector:aSelector];
}
return NULL;
}
- (id)performSelectorIfResponds:(SEL)aSelector withObject:(id)anObject
{
if ([self respondsToSelector:aSelector]) {
return [self performSelector:aSelector withObject:anObject];
}
return NULL;
}
@end
Sau đó, bạn chỉ đơn giản có thể làm:
[delegate performSelectorIfResponds:@selector(optionalMethod)];
đề xuất tốt đẹp :) – Kevlar
........ Whats HOM? – bandejapaisa
HOM = Nhắn tin đặt hàng cao hơn. –
Blocks có thể cung cấp một giải pháp tốt hơn. Chúng cho phép để có điều kiện thực hiện bất kỳ mã dựa trên sự tồn tại của một thực hiện một phương pháp đưa ra:
-(void) performBlock:(void (^)(void))block ifRespondsTo:(SEL) aSelector{
if ([self respondsToSelector:aSelector]) {
block();
}
}
Bằng việc sử dụng bổ sung này để NSObject, bạn có điều kiện có thể thực hiện bất kỳ phương pháp @optional, dù có bao nhiêu thông số nó có thể có .
Xem How to safely send @optional protocol messages that might not be implemented
giải pháp Blocks này hoạt động tốt, một khi bạn nhận được đầu của bạn quấn quanh những gì đang xảy ra. Tôi đã thêm một kết quả BOOL vì tôi muốn có thể điều kiện chạy một trong một số phương pháp tùy chọn. Một số mẹo nếu bạn đang cố triển khai giải pháp này:
Trước tiên, nếu bạn chưa gặp phải Tiện ích mở rộng/Danh mục, bạn chỉ cần thêm phần này vào đầu lớp học của mình, NGOÀI định nghĩa lớp hiện tại. Nó sẽ là một phần mở rộng công cộng hoặc riêng dựa trên nơi bạn đặt nó.
@implementation NSObject (Extensions)
// add block-based execution of optional protocol messages
-(BOOL) performBlock:(void (^)(void))block ifRespondsTo:(SEL) aSelector
{
if ([self respondsToSelector:aSelector]) {
block();
return YES;
}
return NO;
}
@end
Thứ hai, đây là cách bạn gọi nó là từ mã của bạn:
BOOL b = [(NSObject*)self.delegate performBlock:^{
// code to run if the protocol method is implemented
}
ifRespondsTo:@selector(Param1:Param2:ParamN:)];
Thay Param1: param2: ParamN: với tên của mỗi tham số cho phương pháp giao thức của bạn. Mỗi người nên kết thúc bằng dấu hai chấm. Vì vậy, nếu phương pháp giao thức của bạn trông giống như:
-(void)dosomething:(id)blah withObj:(id)blah2 andWithObj(id)blah3;
dòng cuối cùng sẽ trông như thế này:
ifRespondsTo:@selector(dosomething:withObj:andWithObj:)];
- 1. phương thức gọi tại thời gian chạy
- 2. Thực hiện giao diện tại thời gian chạy: phương thức get_Value không được triển khai
- 3. Tìm thời gian thực hiện Phương thức
- 4. Kiểm tra xem phương thức giao thức tùy chọn đã được triển khai chưa
- 5. Tại sao có thể gọi phương thức trên phương thức giao diện Java? [So sánh]
- 6. Phương thức HttpModule Init được gọi nhiều lần - tại sao?
- 7. Phương thức gọi bên trong phương thức khác trong javascript?
- 8. ném RuntimeException khi gọi phương thức chưa được khóa
- 9. Hiểu các giao dịch mùa xuân - Điều gì sẽ xảy ra khi một phương thức giao dịch gọi một phương thức giao dịch khác?
- 10. Tại sao Thuộc tính được thực thi chậm hơn so với Thực thi Phương thức hoặc Phương thức?
- 11. C# Giao diện với các phương thức tùy chọn
- 12. Phương thức lớp hoạt động khác khi được gọi là phương thức thể hiện?
- 13. Tại sao WCF tạo ra các phương thức giao thức hợp đồng gói proxy với các phương thức mới với các chữ ký khác nhau?
- 14. Tại sao biên dịch C# gọi phương thức sản để gọi phương thức BaseClass trong IL
- 15. thực hiện giao diện với phương thức riêng trong vb.net
- 16. Thời gian chờ phương thức MSMQ Receive()
- 17. Sự khác nhau giữa việc sử dụng giao thức không chính thức trên NSObject hoặc giao thức với các phương thức tùy chọn là gì?
- 18. Khi phương thức AppInitialize được gọi trong ASP.NET?
- 19. Phương thức chưa xác định password_changed? Lỗi
- 20. Gọi một phương thức có tên là "chuỗi" tại thời gian chạy trong Java và C
- 21. Phương thức nào được gọi khi một QGraphicsItem được chọn
- 22. Tại sao chúng ta gọi phương thức doesNotRecognizeSelector:?
- 23. Thực hiện hành động tùy chỉnh khi phương thức void giả định được gọi là
- 24. Phương thức System.currentTimeMillis() có thực sự trả về thời gian hiện tại không?
- 25. phương thức gọi lớp php từ phương thức tĩnh bên trong cùng một lớp nhưng không được thực hiện
- 26. Ví dụ thế giới thực của các phương thức giao thức @optional
- 27. Làm thế nào để có được MethodInfo của phương thức giao diện, khi thực hiện MethodInfo của phương thức lớp?
- 28. OCMock: Giao thức giả mạo với các phương thức tùy chọn
- 29. Phương thức gọi từ BackgroundWorker
- 30. Làm cách nào để tìm các phương thức được khai báo, khi thực hiện tải lắp ráp thời gian chạy?
Tôi nghi ngờ càng nhiều, nhưng tôi đã hy vọng tôi sẽ không cần phải thêm những if-kiểm tra trên tất cả các mã. Cảm ơn con trỏ. – Kevlar