Может ли категория одновременно реализовывать протокол? - PullRequest
27 голосов
/ 01 ноября 2009

Если категория, которую я создаю для класса, добавляет методы, которые также выполняют контракт, установленный протоколом, я хотел бы пометить этот класс категории как реализующий протокол, и тем самым указать предварительно процессор, который класс эффективно реализует протокол.

Пример делегата (для ясности, спасибо Оле!):

@protocol SomeDelegate <NSObject>
  - (void)someDelegateMessage;
@end

Пример категории:

@interface NSObject (SomeCategory) <SomeDelegate>
  - (void)someDelegateMessage;    
@end

И с другой типичной реализацией

@implement NSObject (SomeCategory)
  - (void)someDelegateMessage {}
@end

Когда я на самом деле пытаюсь это сделать, я получаю предупреждение для каждого метода NSObject:

предупреждение: неполная реализация категории SomeCategory

предупреждение: определение метода для '-description' не найдено

...

предупреждение: определение метода для -isEqual: не найдено

предупреждение: категория «SomeCategory» не полностью реализует протокол «NSObject»

Работает нормально, если я удаляю <SomeDelegate> из объявления, но, конечно, NSObject не распознается как SomeDelegate

Ответы [ 3 ]

13 голосов
/ 01 ноября 2009

Обходной путь - объявить протокол для категории без реализации и внедрить метод в другой категории, например ::10000

@interface NSObject (SomeCategory) <SomeDelegate>
  - (void)someDelegateMessage;    
@end

@implementation NSObject (SomeCategory_Impl)
  - (void)someDelegateMessage {}
@end

Если вы сделаете это, NSObject будет считаться соответствующим <SomeDelegate> во время компиляции, и проверки во время выполнения для someDelegateMessage пройдут успешно. Однако conformsToProtocol: проверки во время выполнения завершатся неудачей.

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

5 голосов
/ 01 ноября 2009

Есть ли вероятность, что ваша декларация включает протокол NSObject? Как это:

@protocol SomeDelegate <NSObject>
...

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

1 голос
/ 01 ноября 2009

Если вы хотите, чтобы компилятор заткнулся о отправке сообщений (и важно, чтобы вы помнили, что это имя протокола, а не имя класса), тогда просто используйте переменные 'id', а не 'id', так как это вы явно говорит компилятору: «Это объект, который реализует только протокол SomeDelegate».

Альтернативно, используйте вместо этого NSObject в качестве типа переменной.

...