Зачем использовать протокол NSObject для реализации протокола

Я видел код, похожий на следующий:

@protocol MyProtocol <NSObject>
// write some methods.
@end

Есть ли какая-то конкретная причина, по которой MyProtocol соответствует протоколу NSObject? Разве это не слишком избыточно, если вы делаете что-то вроде:

id <MyProtocol> foo; // foo here conforms to NSObject AND MyProtocol?

Просто интересно, что такое логика.

Ответ 1

Я уверен, что причина, по которой вы это сделаете, - добавить к вашему протоколу членов NSObject (например, сохранить и освободить). Технически вы все равно можете отправлять эти сообщения, но вы получите предупреждение компилятора без него.

Ответ 2

Когда вы объявляете переменную типа

 id<MyProtocol> var;

компилятор Objective-C знает только о методах в MyProtocol и, таким образом, выдает предупреждение, если вы попытаетесь вызвать любой из методов NSObject, например -retain/-release, в этом экземпляре. Таким образом, Cocoa определяет протокол NSObject, который отражает методы класса и экземпляра NSObject. Объявив, что MyProtocol реализует протокол NSObject, вы даете компилятору намек на то, что все методы NSObject будут реализованы экземпляром, который реализует MyProtocol.

Почему все это необходимо? Objective-C позволяет объектам спускаться из любого корневого класса. В Cocoa NSObject является наиболее распространенным, но не единственным корневым классом. NSProxy также является корневым классом. Поэтому экземпляр типа id не обязательно наследует методы NSObject.

Ответ 3

Это также очень удобно, когда у вас есть протоколы с @optional методами (например, "современные" Objective-C делегаты 2.0 часто используют этот метод). Если вы не включили протокол NSObject, вы получите предупреждения, когда вы пытаетесь вызвать respondsToSelector: на объект.

Ответ 4

Я никогда не делал этого в своем коде, но я мог видеть его преимущество. Если вы передадите параметр как id <SomeProtocol>, вам нужно будет повторно его переслать, если вы хотите вызвать любой из методов NSObject на этом объекте.

Ответ 5

Если вы используете какой-либо из методов протокола NSObject, таких как сохранение, выпуск, класс, имя класса, компилятор предоставит вам предупреждения, если ваш протокол также не содержит протокол NSObject.