2010-01-30 78 views
4

我爲ObjC類創建了自己的委託。該類本身處理核心數據操作。委託方法用於通知其他類關於發生在數據存儲上的變化。處理數據存儲的類稱爲Datastore,它的委託稱爲DatastoreDelegate。我的UIViewController(ContactsViewController)實現了委託。作爲跟隨委託方法似乎是@required,它被聲明爲@optional

我DatastoreDelegate聲明:

@class Datastore; 
@protocol DatastoreDelegate <NSObject>; 
@optional 
- (void)didAddMessage:(Message *)message; 
- (void)didUpdateContact:(Contact *)contact; 
- (void)didAddContact:(Contact *)contact; 
- (void)didUpdateContact:(Contact *)contact; 
- (void)didDeleteContacts; 
@end 

奇怪的是,我的代碼都能正常運作這些方法除了[didAddMessage:]方法。每當我嘗試從Datastore類中調用此委託時,我都會從ContactsViewController中獲取一個錯誤。該錯誤告訴我在ContactsViewController實例(發送給實例的無法識別的選擇器)中缺少[didAddMessage:]選擇器。如果選擇器是可選的,該如何丟失?

我應該注意到我的Datastore類是一個Singleton。我不確定這是否與我遇到的這個問題有關。

回答

23

「可選」意味着調用者是負責檢查目標響應一個給定的選擇。例如: -

if ([_myDelegate respondsToSelector:@selector(didAddMessage:)]) 
{ 
    [_myDelegate didAddMessage:theMessage]; 
} 
4

你實現你的ContactsViewControllerdidAddMessage:?它是可選的,所以你不必強制執行它,但是如果你發送didAddMessage:消息到ContactsViewController,但實際上沒有在ContactsViewController中實現它,你仍然會得到一個編譯器警告。換句話說,@optional意味着你不必實現它,但是如果你還沒有實現它,但是嘗試使用它,編譯器仍然可能會發出警告。

什麼你可能想在Datastore做的是這樣的:

if ([delegate respondsToSelector:@selector(didAddMessage:)]) { 
    [delegate didAddMessage:theMessage]; 
} 

,而不僅僅是:

[delegate didAddMessage:theMessage]; 

(你還是會在第一時間拿到例如編譯器警告,但它是安全的忽略,因爲你在運行時檢查,看是否合適的方法是在委託實現)

+0

感謝時,[respondsToSelector:]消息固定我的問題。當消息本身被聲明爲@optional時,需要這樣的消息很奇怪。 – 2010-01-30 19:47:52

+0

想一想:如果該方法是可選的,那麼委託類可能沒有實現它。如果您發送委託人未回覆的郵件,則會發生崩潰(默認情況下)。 – mipadi 2010-01-30 19:52:53

+0

@optional僅僅意味着一個說它滿足協議的類並不需要實現該方法。令你感到困惑的事情 - 調用者檢查[respondsToSelector:] - 是所有委託消息的工作方式。 – 2010-01-30 19:53:27