2012-01-06 62 views
6

我知道協議的指令是@protocol就像@選擇器一樣,但是引用一個協議的「類型」是什麼(比如@Selector的SEL)?在MacOSX堆棧中,它是協議*?如何在Objective-C中引用協議?

回答

13

可引用它作爲:

id<TheNameOfTheProtocol> aVariableToThatProtocol; 

或者,如果一個消息想要一個(Protocol *)對象:

[myObject conformsToProtocol:@protocol(TheNameOfTheProtocol)]; 
+0

只是好奇,有什麼理由的協議 「類型」 必須用「ID使用?」從C#背景來看,由於您只是將其聲明類似於類引用(即IProtocol協議;),所以將接口引用可視化會更容易一些。 – 5StringRyan 2012-01-06 17:43:07

+0

@ 5StringRyan我不知道推理,但是'id'類型是任何對象的一般類型,即使它不是NSObject。這種語法的一個優點是它允許多種協議。你可以按照'id '的方式做一些事情來表達對象符合兩種協議。或者,如果您的協議不符合NSObject,但您引用的類實例可以執行以下操作:'id '。 – 2012-01-06 17:52:56

+3

@ 5StringRyan該類型確實*不*必須是'id'。例如:'NSArray * var = [NSArray array];'有時是合法的。你也可以寫'NSArray * var = [NSArray array];'sooo ...這當然是注入某種類型安全的好方法。 (這些例子很愚蠢 - 它們只是演示語法) – justin 2012-01-06 18:06:16

4

id <YourProtocol> delegate(其被用於引用協議)?

我所提到的蘋果的官方DOC,並發現了一個簡單的例子來參照其它協議在一個協議:

#import "B.h" 

@protocol B; // To break the recursive cycle, you must use the @protocol directive to make a forward reference to the needed protocol instead of importing the interface file where the protocol is defined 

@protocol A 
    - foo:(id <B>)anObject; 
@end 

其中協議B可以聲明如下:

#import "A.h" 

@protocol B 
    - bar:(id <A>)anObject; 
@end 

請注意,以這種方式使用@protocol指令只是通知編譯器B是稍後定義的協議。它不會導入定義協議B的接口文件。你想


而且我這裏還有更多的事情瞭解:

在很多方面,協議類似於類定義。它們都聲明方法,並且在運行時它們都由對象來表示,它們由Class的實例和Protocol的實例來表示。像類對象一樣,協議對象是從源代碼中的定義和聲明中自動創建的,並被運行時系統使用。 它們沒有在程序源代碼中分配和初始化。

源代碼可以是指協議對象使用@protocol()指令聲明協議-the相同的指令,所不同的是在這裏它具有一組拖尾括號。括號包圍協議名稱:

Protocol *myXMLSupportProtocol = @protocol(MyXMLSupport); 

這是源代碼可以變出協議對象的唯一途徑。與類名不同,協議名稱不指定對象,除了@protocol()內部。


而且更重要的是,該可以通過發送一個conformsToProtocol:消息來檢查對象是否符合協議:

if (! [receiver conformsToProtocol:@protocol(MyXMLSupport)] ) { 
    // Object does not conform to MyXMLSupport protocol 
    // If you are expecting receiver to implement methods declared in the 
    // MyXMLSupport protocol, this is probably an error 
} 

conformsToProtocol:測試樣respondsToSelector:測試一個單一的方法,除了它測試協議是否被採用(並且大概所有的它聲明的方法被實現),而不僅僅是一個特定的方法是否被實現。因爲它檢查協議中的所有方法,所以conformsToProtocol:可以比respondsToSelector更有效:

conformsToProtocol:測試也是像isKindOfClass:測試,不同之處在於它測試用於基於協議,而不是基於繼承層次一個類型的類型。

2

這是一樣的OS X:

Protocol * p = objc_getProtocol("UITableViewDataSource"); 

它宣佈<objc/runtime.h>

typedef struct objc_object Protocol;