为什么要将NSObject的协议添加到协议实现中

Coo*_*coa 31 iphone cocoa objective-c

我一直在看到一些类似于以下内容的代码:

@protocol MyProtocol <NSObject>
// write some methods.
@end
Run Code Online (Sandbox Code Playgroud)

MyProtocol符合NSObject协议有什么特别的原因吗?如果你做的事情如下:

id <MyProtocol> foo; // foo here conforms to NSObject AND MyProtocol?
Run Code Online (Sandbox Code Playgroud)

只是好奇逻辑是什么.

Bar*_*ark 31

当你声明一个变量时

 id<MyProtocol> var;
Run Code Online (Sandbox Code Playgroud)

Objective-C编译器只知道其中的方法,MyProtocol因此如果您尝试调用该实例上的任何NSObject方法,则会产生警告-retain/-release.因此,Cocoa定义了一个NSObject镜像NSObject类和实例方法的协议.通过声明MyProtocol实现NSObject协议,您可以为编译器提供一个提示,即所有NSObject方法都将由实现的实例实现MyProtocol.

为什么这一切都是必要的?Objective-C允许对象从任何根类下降.在Cocoa中,NSObject是最常见的,但不是唯一的根类.NSProxy例如,也是一个根类.因此类型的实例id并不一定继承NSObject的方法.

  • 如果您的协议不符合NSObject,我发现最好使用`id <MyProtocol,NSObject>`.一个原因是使用`id`的动态类型允许您调用编译器可以找到声明的任何方法(没有警告),而不仅仅是从NSObject继承或在协议中声明的方法.这可能既危险又非常有用,取决于您是否做出安全的假设.:-) (3认同)
  • 为什么你不能只做“NSObject &lt;Protocol&gt; *variable”?那么你知道它是从 NSObject 派生的,但也符合协议,那么编译器就不会抱怨保留和释放。 (2认同)

Lou*_*ges 28

我很确定你这样做的原因是将NSObject成员(比如retain和release)添加到你的协议中.从技术上讲,你仍然可以发送这些消息,但没有它你会收到编译器警告.

  • "从技术上讲,你仍然可以发送这些消息"如果你不知道它实现了NSObject协议,那么无法保证对象能够理解这些消息. (2认同)

Ale*_*lex 22

当你拥有具有@optional方法的协议时(例如"现代"Objective-C 2.0委托经常使用这种技术),它也非常方便.如果你不包含NSObject协议,当你试图调用respondsToSelector:该对象时,你会收到警告.

  • 尼斯.这比现在接受的答案更具相关性,因为ARC消除了任何人担心保留/释放的需要. (5认同)