2012-01-06 61 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;