2015-07-03 48 views
1

指定給自定義協議引用的任何對象總是由NSObject協議直接或按超類來確認。那麼,爲什麼我應該這樣做?爲什麼要將自定義協議符合NSObject?

+0

也許你可以舉個例子嗎? – Caleb

+0

誰說你必須這樣做? – holex

+0

你的標題應該說'符合'而不是'確認'你符合協議,你不確認。 –

回答

0

Cocoa定義了一個NSObject協議,它反映了NSObject類和實例方法。通過聲明您的自定義協議實現NSObject協議,您可以向編譯器提供一個提示,即所有NSObject方法都將由實現您的自定義協議的實例實現。

如果您不包含NSObject協議,當您嘗試調用對象上的實例respondsToSelector的任何NSObject方法時,您將收到警告。

1

這聽起來像你可能會試圖問關於使用NSObject協議,因爲每個類都有NSObject作爲祖先。

答案是,它的不是確實每個對象都是從NSObject派生而來的。大部分是,但NSProxy是一個不是的例子。在NSObject協議的方法是什麼NSObject的任何實例有望實現,所以通過實現NSObject協議NSProxy能夠提供任何類從NSObject(類)得出同樣的行爲已。

例如,您可以使用像-isEqual-hash這樣的方法,並使用NSProxy的實例。

如果您正在創建NSObject類的子類,則不需要聲明您的類實現NSObject協議,因爲NSObject類已經爲您執行了該操作。

而且,正如你可以聲明一個類採用協議與:

@interface MyClass <SomeProtocol> 

你也可以聲明一個協議採用另一種協議:

@interface MyProtocol <SomeProtocol> 

因爲,如上所述,不是類是NSObject(該類)的子類,具有MyProtocol採用NSObject(該協議)保證您可以調用NSObject方法。如果要指定方法採用任何類型的採用YourProtocol的對象,則可以通過將類型指定爲id<YourProtocol>來完成此操作。但是,如果YourProtocol未聲明採用NSObject協議,則無法確定可以安全地調用NSObject方法(如-isEqual),並且您甚至無法使用-respondsToSelector:-isKindOfClass:檢查它是否安全,因爲這些方法本身都是部分的NSObject協議。

+1

這可能是我的更好的解釋!但是當我第一次潛入水中的時候,我把它看作是面對面的價值。 –

+0

Caleb,正如你所說的,並不是每個類都是從NSObject類派生的。因此,如果我從NSObject採用MyProtocol,那麼我可以使用-isEqual,respondsToSelector :,等等。但是在這種情況下,我將不得不爲這些函數提供什麼在NSObject協議中聲明的主體。 –

+0

只要你的類來自NSObject,你就已經有了這些方法的實現。如果它不(這將是非常不尋常的),那麼是的,你需要提供它們。 – Caleb

0

你不要到。但問題在於,NSObject的許多核心功能 - 實際上,NSObject作爲基類所需的所有核心功能 - 都是在NSObject協議中聲明的。 (這個奇怪的架構使NSObject和NSProxy都可以成爲基類:它們都採用NSObject協議。)

現在,如果將對象的類型聲明爲id<MyDelegate>,則可以發送該對象的唯一消息是MyDelegate消息。這很好,通常;但是如果你想發送它,比如說respondsToSelector:消息呢?該方法在NSObject協議中聲明,而不是在MyDelegate協議中聲明。所以編譯器會阻止你。

有兩種解決方案。要麼將對象的類型聲明爲NSObject<MyDelegate>,要麼使MyDelegate採用NSObject協議。無論哪種方式,現在編譯器都滿意了,您可以發送此對象的消息respondsToSelector:

1

我真的不知道,我是否知道你是對的。

如果您的意思是一個自定義協議總是確認NSObject協議,那麼其原因很簡單。這有些奇怪:

如果您鍵入對id的引用,編譯器會接受編譯翻譯單元(「class」,「module」,您編譯的文件)時他看到的每條消息。

如果您鍵入對id<protocol>的對象引用,編譯器只接受在協議內聲明的消息。但這永遠不夠!

@protocol MyProtocol 
@optional 
- (void)doItOrNot; 
@end 

您可以發送的唯一信息是-doItOrNot。所以,這樣的代碼的編譯將失敗:

id<MyProtocol> ref = …; 
if ([ref respondsToSelector:@selector(doItOrNot)]) // <- Error -respondsToSelector is not declared in the protocol. 
… 

通過添加NSObject協議的協議導入一些基本的聲明。 (包括MM for MRC)

+0

如果我使用 - NSObject *委託; 然後它不會給編譯錯誤,respondsToSelector:在NSObject類中聲明。 –

+0

當然,因爲NSObject類實現了NSObject協議。但是這是對Objective-C不需要的類的依賴。您不需要類「NSObject」,您需要該協議。 –

相關問題