Может ли категория одновременно реализовать протокол?
Если категория, которую я создаю для класса, добавляет методы, которые также выполняют контракт, установленный протоколом, я хотел бы отметить этот класс категории как реализацию протокола и тем самым указать Obj-C pre- процессор, который класс эффективно реализует протокол.
Пример делегата (для ясности, спасибо Ole!):
@protocol SomeDelegate <NSObject>
- (void)someDelegateMessage;
@end
Пример категории:
@interface NSObject (SomeCategory) <SomeDelegate>
- (void)someDelegateMessage;
@end
И с обычной типичной реализацией
@implement NSObject (SomeCategory)
- (void)someDelegateMessage {}
@end
Когда я на самом деле пытаюсь это сделать, я получаю предупреждение для каждого метода NSObject:
предупреждение: неполная реализация категории "SomeCategory"
предупреждение: определение метода для '-description' not found
...
предупреждение: определение метода для '-isEqual:' not found
warning: category 'SomeCategory' не полностью реализует протокол NSObject
Прекрасно работает, если я удаляю <SomeDelegate>
из объявления, но, конечно, NSObject не распознается как SomeDelegate
Ответы
Ответ 1
Обходной путь заключается в объявлении протокола для категории без реализации и реализации метода в другой категории, например:
@interface NSObject (SomeCategory) <SomeDelegate>
- (void)someDelegateMessage;
@end
@implementation NSObject (SomeCategory_Impl)
- (void)someDelegateMessage {}
@end
Если вы это сделаете, NSObject
будет считаться совместимым с <SomeDelegate>
во время компиляции, а проверки выполнения для someDelegateMessage
будут успешными. Однако проверка выполнения conformsToProtocol:
не выполняется.
Конечно, вы должны записать ошибку, запрашивая, чтобы методы, объявленные в основном классе, не генерировали предупреждений.
Ответ 2
Любая возможность объявления протокола включает протокол NSObject
? Вот так:
@protocol SomeDelegate <NSObject>
...
То, откуда появляются предупреждения, потому что теперь ваша категория не реализует полный протокол. В тестовом коде, который я только что напечатал, удаление NSObject
из протокола удаляет предупреждения компилятора.
Ответ 3
Если вы хотите, чтобы компилятор заткнулся о передаче <NSObject> (и важно, чтобы вы помнили, что это имя протокола, а не имя класса), тогда просто используйте переменные id, а не идентификатор, поскольку это явное указание компилятору "Это объект, который реализует только протокол SomeDelegate",.
В качестве альтернативы используйте NSObject вместо вашего типа переменной.