Должны ли протоколы соответствовать протоколу NSObject?

Протокол NSObject поставляется с шаблонами протокола запаса, но он, по-видимому, не является необходимым для фактических реализаций протокола. Оставляя это, кажется, совершенно ничего не меняет. Итак, действительно ли необходимо, чтобы протокол наследовал от него, или это просто лишнее дополнение?

Ответы

Ответ 1

В течение многих лет я (и многие подобные мне) не соответствовал нашим протоколам <NSObject>. Он работает нормально. Но это часто может раздражать. Наиболее распространенная досада заключается в том, что вы не можете использовать respondsToSelector:, не возвращаясь к NSObject* (какой вид побеждает весь смысл протокола). Это не имело значения в днях ObjC1, потому что не было @optional, поэтому никто из нас не беспокоился об этом (мы не использовали протоколы вообще в те дни, так как без @optional они были не такими полезными), Затем ObjC2 пришел с замечательным добавлением дополнительных методов, и вдруг respondsToSelector: имел значение. Потребовалось немного времени для нас медленнее, но в итоге мы начали выяснять, что жизнь была намного проще, если ваши протоколы соответствуют <NSObject>. Благословенно это теперь пробилось в Xcode, что облегчает для всех делать вещи более удобным способом.

Но нет, вам не обязательно это делать. Во многих случаях это не имеет значения. Но не так много причин не делать этого, поэтому я рекомендую его.

Ответ 2

Не обязательно. Делегат - это всего лишь вспомогательный объект - единственными требованиями являются те, которые на нем делегирующий класс. Если вы хотите формализовать требования к определенному делегату, создайте формальный протокол, то есть объявите протокол, используя директиву @protocol. Если соответствие протоколу NSObject является одним из этих требований, вы можете заставить его принять его:

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

Тем не менее, я не вижу причин создавать делегат, который не является производным от NSObject или, возможно, NSProxy, и оба эти класса уже соответствуют протоколу NSObject.

Ответ 3

Не каждый объект должен подкласса NSObject, поэтому я предполагаю, что если вы ожидали, что такой объект будет соответствовать вашему протоколу, он не обязательно должен соответствовать NSObject.

Соответствие NSObject позволяет компилятору знать, что объект соответствует основам - проверьте Ссылка на протокол NSObject. Не сказав, что я согласен с NSObject, как компилятор знает, что я согласен с этим?

NSObject определяется как

@interface NSObject <NSObject> {
    Class   isa;
}

тогда как id определяется как

typedef struct objc_object {
    Class isa;
} *id;

Итак, для id компилятор не знает, что он соответствует NSObject

Ответ 4

Рекомендовать и не обязательно.

Согласно официальному документу Apple ProgrammingWithObjectiveC.pdf

Если вы попытаетесь вызвать метод respondsToSelector: на идентификаторе в соответствии с протоколом, как определено выше, вы получите компилятор ошибка, что для него нет известного метода экземпляра. Как только вы идентификатор с протоколом, возвращается всестатическая проверка типов; ты получишь ошибка, если вы попытаетесь вызвать любой метод, который не определен в указанный протокол. Один из способов избежать ошибки компилятора - установить пользовательский протокол для принятия протокола NSObject.

протокол, как он определен выше, является протоколом, не соответствующим протоколу NSObject.

В качестве примера рекомендуется использовать ваши протоколы для соответствия к протоколу NSObject (некоторые из действий NSObject разделены на его интерфейс класса в отдельный протокол; класс NSObject принимает протокол NSObject).