Может ли категория одновременно реализовывать протокол?
-
11-09-2019 - |
Вопрос
Если категория, которую я создаю для класса, добавляет методы, которые также выполняют контракт, установленный протоколом, я хотел бы пометить этот класс категории как реализующий протокол, и тем самым указать препроцессору Obj-C, что класс также эффективно реализует протокол.
Пример делегирования (для наглядности, спасибо Ole!):
@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
Решение
Обходной путь заключается в объявлении протокола в категории, не имеющей реализации, и реализации метода в другой категории, например:
@interface NSObject (SomeCategory) <SomeDelegate>
- (void)someDelegateMessage;
@end
@implementation NSObject (SomeCategory_Impl)
- (void)someDelegateMessage {}
@end
Если ты сделаешь это, NSObject
будет считаться соответствующим <SomeDelegate>
во время компиляции и выполнения проверяет наличие someDelegateMessage
добьется успеха.Однако, conformsToProtocol:
проверки во время выполнения завершатся неудачей.
Конечно, вам следует файл с ошибкой запрос на то, чтобы методы, объявленные в основном классе, не генерировали предупреждений.
Другие советы
Есть ли вероятность, что ваша декларация протокола включает в себя NSObject
протокол?Вот так:
@protocol SomeDelegate <NSObject>
...
Вот откуда приходят предупреждения, потому что теперь ваша категория не реализует полный протокол.В тестовом коде, который я только что ввел, удалив NSObject
из протокола удаляются предупреждения компилятора.
Если вы хотите, чтобы компилятор заткнулся по поводу отправки <NSObject> сообщения (и важно, чтобы вы помнили, что это имя протокола, а не имя класса), затем просто используйте переменные 'id', а не 'id', поскольку вы явно сообщаете компилятору "Это объект, который реализует только протокол SomeDelegate".
В качестве альтернативы вместо этого используйте NSObject в качестве типа переменной.