20

NSObject 协议带有库存协议模板,但对于协议的实际实现来说,它似乎并不是所有必需的。离开它似乎完全没有改变。那么,协议是否真的有必要继承它,或者它只是一个不必要的附加组件?

4

4 回答 4

22

多年来,我(以及许多像我一样的人)没有让我们的协议符合<NSObject>. 它工作正常。但这通常很烦人。respondsToSelector:最常见的烦恼是,如果不回滚就无法使用NSObject*(这会破坏协议的全部意义)。在 ObjC1 时代这并不重要,因为没有@optional,所以我们都不担心它(那时我们根本没有使用协议,因为没有@optional它们就没那么有用了)。然后 ObjC2 伴随着可选方法的精彩添加而出现,并突然变得respondsToSelector:重要。我们这些速度较慢的人花了一点时间,但最终我们开始发现,如果你让你的协议符合<NSObject>. 幸运的是,现在这已经进入了 Xcode,让每个人都可以更轻松地以更方便的方式做事。

但不,你不必这样做。在很多情况下都无所谓。但是没有太多理由不这样做,所以我推荐它。

于 2012-04-06T23:54:22.520 回答
7

不必要。委托只是一个辅助对象——唯一的要求是委托类放在它上面的那些。如果你想正式化给定委托的要求,创建一个正式的协议,即使用@protocol指令声明一个协议。如果符合 NSObject 协议是这些要求之一,您可以让您的协议采用它:

@protocol MyDelegateProtocol <NSObject>
//...
@end

也就是说,我看不出有任何理由创建一个不是从 NSObject 或可能是 NSProxy 派生的委托,而且这两个类已经符合 NSObject 协议。

于 2012-04-06T21:52:32.817 回答
1

不是每个对象都必须子类化NSObject,所以我猜如果您期望这样的对象符合您的协议,它不一定必须符合 NSObject。

符合 NSObject 让编译器知道该对象符合基本要求 - 请查看NSObject 协议参考。不用说我符合 NSObject 编译器怎么知道我符合这些?

NSObject定义为

@interface NSObject <NSObject> {
    Class   isa;
}

id定义为

typedef struct objc_object {
    Class isa;
} *id;

所以对于id编译器不知道它符合NSObject

于 2012-04-06T21:54:00.930 回答
1

推荐而不是强制。

根据苹果官方文档ProgrammingWithObjectiveC.pdf

如果您尝试在respondsToSelector:符合上面定义的协议的 id 上调用该方法,您将收到一个编译器错误,即没有已知的实例方法。一旦你用协议限定了一个 id,全静态类型检查就会回来;如果您尝试调用未在指定协议中定义的任何方法,您将收到错误消息。避免编译器错误的一种方法是将自定义协议设置为采用 NSObject 协议。

上面定义的协议是不符合协议的NSObject协议。

例如,最好将协议定义为符合 NSObject 协议(一些 NSObject 行为从其类接口拆分为单独的协议;NSObject 类采用 NSObject 协议)。

于 2015-06-29T23:52:33.397 回答