如何在Objective-C中引用协议?

LB.*_*LB. 7 objective-c ios

我知道协议的指令是@protocol,就像@selector一样,但引用协议的"类型"是什么(例如@Selector的SEL)?在MacOSX堆栈中,它的协议*?

Dav*_*d V 13

您将其引用为:

id<TheNameOfTheProtocol> aVariableToThatProtocol;
Run Code Online (Sandbox Code Playgroud)

或者如果消息想要一个(Protocol *)对象:

[myObject conformsToProtocol:@protocol(TheNameOfTheProtocol)];
Run Code Online (Sandbox Code Playgroud)

  • @ 5StringRyan类型确实*不*需要是`id`.例如:`NSArray <NSCopying>*var = [NSArray数组];`有时肯定是有用的.你也可以写`NSArray <NSObject,NSCopying>*var = [NSArray array];`sooo ...它肯定是注入某种类型安全的好方法.(这些例子很愚蠢 - 他们只演示语法) (3认同)

Kju*_*uly 5

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
Run Code Online (Sandbox Code Playgroud)

其中协议 B 声明如下:

#import "A.h"

@protocol B
  - bar:(id <A>)anObject;
@end
Run Code Online (Sandbox Code Playgroud)

请注意,以这种方式使用@protocol 指令只是通知编译器 B 是稍后定义的协议。它不导入定义了协议 B 的接口文件。


这里有更多你想知道的事情protocol

在许多方面,协议类似于类定义。它们都声明方法,并且在运行时它们都由对象表示——类由 Class 的实例表示,协议由 Protocol 的实例表示。与类对象一样,协议对象是根据源代码中的定义和声明自动创建的,并由运行时系统使用。它们不在程序源代码中分配和初始化。

源代码可以使用@protocol() 指令引用协议对象——与声明协议的指令相同,只是这里有一组尾括号。括号括起协议名称:

   Protocol *myXMLSupportProtocol = @protocol(MyXMLSupport);
Run Code Online (Sandbox Code Playgroud)

这是源代码可以唤起协议对象的唯一方式。与类名不同,协议名不指定对象——除了在@protocol() 内部。


更重要的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
}
Run Code Online (Sandbox Code Playgroud)

所述conformsToProtocol:测试是像respondsToSelector:测试的单一方法,不同之处在于它测试一个协议是否已被采用(大概所有的方法,它声明实现),而不是一个特定的方法只是是否已经执行。因为它检查协议中的所有方法,conformsToProtocol:可以比RespondsToSelector更高效

所述conformsToProtocol:测试也是像isKindOfClass:测试,不同之处在于它测试用于基于协议,而不是基于继承层次一个类型的类型。