Почему в iPhone SDK для некоторых делегатов используются категории, а не протоколы?

Насколько я понимаю, протоколы похожи на интерфейсы в других языках — они объявляют ожидаемые методы — в то время как категории позволяют вам добавлять новые методы к существующим типам (возможно, даже к типам, которыми вы не владеете).

Почему же тогда iPhone SDK иногда использует категории для объявления типов делегатов? Обычно я ожидаю, что все делегаты будут иметь тип id‹MyDelegateProtocol›, но есть много примеров, когда это не так.

Например, см. нсурлконнектион. Его делегат имеет тип «id», а «контракт» объявлен как категория в NSObject (NSURLConnectionDelegate).

Итак: какова мотивация использования категорий в этих случаях?


person Dave Peck    schedule 22.05.2009    source источник


Ответы (3)


В Objective-C 2.0 появилась директива протокола @Optional, позволяющая объявлять определенные методы протокола необязательными. До Obj-C 2.0 категории использовались для разрешения необязательных методов делегирования (в частности, категорий в NSObject, которые называются неформальными протоколами).

Я предполагаю, что большая часть использования категории вместо протокола в iPhone SDK является пережитком эквивалентных классов Mac. Например, NSURLConnection существует как в Mac, так и в iPhone SDK, поэтому код, скорее всего, является общим. Поскольку Apple еще не изменила все классы Mac для использования формальных протоколов, у нас остается некоторое несоответствие.

person Matt Ball    schedule 22.05.2009
comment
Это было мое предположение, но я не знал наверняка. Спасибо! - person Dave Peck; 23.05.2009
comment
Однако ожидайте, что изменения в протоколах произойдут довольно скоро. Теперь, когда разрешены необязательные методы протокола, их использование немного очистит код и избавит от множества ненужных категорий. (Они классные и все такое, но вместо того, чтобы привязывать методы к NSObject во время выполнения, я думаю, что делегат реализует протокол намного чище, как концептуально, так и с точки зрения времени выполнения.) - person Quinn Taylor; 23.06.2009

До версии Objective-C, которая была выпущена с OS X 10.5 и iPhone SDK под названием «Objective-C 2.0», можно было создавать необязательные протоколы только с использованием категорий. В Objective-C 2.0 в протоколы было добавлено новое ключевое слово @Optional, чтобы отметить, какие методы являются необязательными (остальные неявно обязательны).

Поэтому я думаю, что то, что вы видите, является небольшим пережитком предыдущих дней до ключевого слова @Optional.

Изменить: Чтобы ответить на продолжение, появившееся в исходном вопросе: мотивация использования категории в NSObject/id для неофициального протокола частично заключается в том, чтобы документировать и группировать, какие методы объект может вызывать в своем источнике данных (или делегировать или что-то еще) , и в меньшей степени, чтобы избежать предупреждений компилятора о том, что вы вызываете методы, о которых компилятор не знает, что они будут присутствовать в объекте, который получает вызов. Представьте, что вы реализовали класс, который вызывает эти методы источника данных. Возможно, вам захочется проверить наличие метода с помощью [obj responsesToSelector: @selector(my:datasource:method:)] всякий раз, когда вы заинтересованы в вызове метода my. :datasource:method: метод объекта obj.

person harms    schedule 22.05.2009

Это наследство исходит от Objective-C 1.0, в котором нет «дополнительного метода протокола».

person Community    schedule 23.05.2009