NSObject 协议带有库存协议模板,但对于协议的实际实现来说,它似乎并不是所有必需的。离开它似乎完全没有改变。那么,协议是否真的有必要继承它,或者它只是一个不必要的附加组件?
4 回答
多年来,我(以及许多像我一样的人)没有让我们的协议符合<NSObject>
. 它工作正常。但这通常很烦人。respondsToSelector:
最常见的烦恼是,如果不回滚就无法使用NSObject*
(这会破坏协议的全部意义)。在 ObjC1 时代这并不重要,因为没有@optional
,所以我们都不担心它(那时我们根本没有使用协议,因为没有@optional
它们就没那么有用了)。然后 ObjC2 伴随着可选方法的精彩添加而出现,并突然变得respondsToSelector:
重要。我们这些速度较慢的人花了一点时间,但最终我们开始发现,如果你让你的协议符合<NSObject>
. 幸运的是,现在这已经进入了 Xcode,让每个人都可以更轻松地以更方便的方式做事。
但不,你不必这样做。在很多情况下都无所谓。但是没有太多理由不这样做,所以我推荐它。
不必要。委托只是一个辅助对象——唯一的要求是委托类放在它上面的那些。如果你想正式化给定委托的要求,创建一个正式的协议,即使用@protocol
指令声明一个协议。如果符合 NSObject 协议是这些要求之一,您可以让您的协议采用它:
@protocol MyDelegateProtocol <NSObject>
//...
@end
也就是说,我看不出有任何理由创建一个不是从 NSObject 或可能是 NSProxy 派生的委托,而且这两个类已经符合 NSObject 协议。
不是每个对象都必须子类化NSObject
,所以我猜如果您期望这样的对象符合您的协议,它不一定必须符合 NSObject。
符合 NSObject 让编译器知道该对象符合基本要求 - 请查看NSObject 协议参考。不用说我符合 NSObject 编译器怎么知道我符合这些?
NSObject
定义为
@interface NSObject <NSObject> {
Class isa;
}
而id
定义为
typedef struct objc_object {
Class isa;
} *id;
所以对于id
编译器不知道它符合NSObject
推荐而不是强制。
根据苹果官方文档ProgrammingWithObjectiveC.pdf
如果您尝试在
respondsToSelector:
符合上面定义的协议的 id 上调用该方法,您将收到一个编译器错误,即没有已知的实例方法。一旦你用协议限定了一个 id,全静态类型检查就会回来;如果您尝试调用未在指定协议中定义的任何方法,您将收到错误消息。避免编译器错误的一种方法是将自定义协议设置为采用 NSObject 协议。
上面定义的协议是不符合协议的NSObject
协议。
例如,最好将协议定义为符合 NSObject 协议(一些 NSObject 行为从其类接口拆分为单独的协议;NSObject 类采用 NSObject 协议)。