【问题标题】:Why should I conform Custom Protocol to NSObject?为什么我应该使自定义协议符合 NSObject?
【发布时间】:2015-08-22 18:12:54
【问题描述】:

任何分配给自定义协议引用的对象,总是由 NSObject 协议直接或超类确认。那我为什么要这样做呢?

【问题讨论】:

  • 或许你可以举个例子?
  • 谁说你必须这样做?
  • 你的标题应该说“符合”而不是“确认”你符合协议,你不确认它。

标签: ios objective-c iphone protocols nsobject


【解决方案1】:

我真的不知道,我是否正确。

如果您的意思是自定义协议总是与NSObject 协议确认,那么原因很简单。有点奇怪:

如果您键入对id 的引用,编译器会接受他在编译翻译单元(“类”、“模块”、您编译的文件)时看到的所有消息。

如果您键入对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 协议添加到您的协议中,您可以导入一些基本声明。 (包括 MRC 的 MM。)

【讨论】:

  • 如果我使用 - NSObject *delegate;那么就不会编译报错了,responsesToSelector: 是在 NSObject 类中声明的。
  • 当然可以,因为NSObject类实现了NSObject协议。但这是对Objective-C 不需要的类的依赖。你不需要类NSObject,你需要协议。
【解决方案2】:

听起来您可能想询问有关使用NSObject 协议的问题,因为每个类都有NSObject 作为祖先。

因此,答案是不是每个对象都派生自NSObject。大多数是,但NSProxy 是一个不是的例子。 NSObject protocol 中的方法是 NSObject class 的任何实例所期望实现的,因此通过实现 NSObject protocol em>,NSProxy 能够提供与派生自 NSObject(类)的任何类相同的行为。

例如,您可以将-isEqual-hash 等方法用于NSProxy 的实例。

如果您正在创建NSObject 类的子类,则无需声明您的类实现了NSObject 协议,因为NSObject 类已经为您实现了。

此外,正如您可以声明一个类采用协议一样:

@interface MyClass <SomeProtocol>

你也可以声明一个协议采用另一个协议:

@interface MyProtocol <SomeProtocol>

由于如上所述,不是每个类都是NSObject(类)的子类,拥有MyProtocol采用NSObject(协议)保证您可以调用@987654341 @ 方法。如果要指定方法采用采用YourProtocol 的任何类型的对象,可以通过将类型指定为id&lt;YourProtocol&gt; 来实现。但是,如果YourProtocol 没有被声明为采用NSObject 协议,则您无法确定调用NSObject 方法如-isEqual 是否安全,您甚至无法检查使用@ 是否安全987654348@ 或 -isKindOfClass: 因为这些方法本身是 NSObject 协议的一部分。

【讨论】:

  • 这可能是像我这样更好的解释!但是当我第一次潜入时,我对 OOP 的看法是从表面上看的,所以很温和。
  • Caleb ,正如您所说,并非每个类都派生自 NSObject 类。因此,如果我采用 NSObject 的 MyProtocol,那么我可以使用 -isEqual、responsToSelector: 等。但在这种情况下,我必须为这些函数提供 NSObject 协议中声明的主体。
  • 只要你的类继承自 NSObject,你就已经有了这些方法的实现。如果没有(这将是非常不寻常的),那么是的,您需要提供它们。
【解决方案3】:

Cocoa 定义了一个 NSObject 协议,它反映了 NSObject 类和实例方法。通过声明您的自定义协议实现了 NSObject 协议,您可以向编译器提示所有 NSObject 方法都将由实现您的自定义协议的实例实现。

如果您不包含 NSObject 协议,当您尝试调用任何 NSObject 方法时,您将收到警告,例如在对象上调用 respondsToSelector:。

【讨论】:

    【解决方案4】:

    你没有。但问题是 NSObject 的许多核心功能——实际上,NSObject 作为基类运行所必需的所有核心功能——都在 NSObject 协议中声明。 (这种奇怪的架构使得 NSObject 和 NSProxy 都可以是基类:它们都采用 NSObject 协议。)

    现在,如果您将对象的类型声明为id&lt;MyDelegate&gt;,则您可以发送该对象的唯一消息是 MyDelegate 消息。这很好,通常;但是如果你想发送它,比如respondsToSelector: 消息呢?该方法是在 NSObject 协议中声明的,而不是在 MyDelegate 协议中。所以编译器会阻止你。

    有两种解决方案。要么声明对象的类型为NSObject&lt;MyDelegate&gt;,要么让MyDelegate 采用NSObject 协议。无论哪种方式,编译器现在都满意了,您可以向该对象发送respondsToSelector: 消息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-14
      • 1970-01-01
      • 2014-01-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多