Добавление метода категории к NSObject, но получение предупреждений, потому что его нет в протоколе <NSObject>, когда я его вызываю - PullRequest
4 голосов
/ 17 мая 2011

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

Я добавил этот удобный метод в качестве категории в NSObject. (Я добавил другие методы, поэтому мне все еще интересен ответ, даже если вы не согласны с этим конкретным удобным методом.)

@implementation NSObject (MyCategory)
- (void)performInvocationOnMainThread:(NSInvocation *)invocation waitUntilDone:(BOOL)waitForMainThread;
@end

Тогда у меня есть протокол, который я определил:

@protocol MyDelegateProtocol <NSObject>
- (void)myDelegateProtocolMethod;
@end

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

@property (nonatomic, assign) id <MyDelegateProtocol> delegate;

Но когда я пытаюсь вызвать метод NSObject, я добавил в свою категорию примерно так:

NSInvocation *invocation = [self.delegate invocationForSelector:@selector(someSelector:withArg:)];

Я получаю это предупреждение

'-performInvocationOnMainThread:waitUntilDone:' not found in protocol(s)

Если я назначу своего делегата как (NSObject *), я не получу предупреждение. Что я делаю неправильно? Не похоже, что я мог (или должен?) Добавлять методы к существующему протоколу, не создавая «вспомогательный протокол» и не используя его с тех пор. (Какой вид победы над точкой добавления методов в NSObject имеется в виду.)

NSInvocation *invocation = [(NSObject *)self.delegate invocationForSelector:@selector(someSelector:withArg:)];

Ответы [ 2 ]

5 голосов
/ 17 мая 2011

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

Именно поэтому приведение типов к типу указателя NSObject * работает; вы приводите класс NSObject, а не что-то вроде id<NSObject>, что означает произвольный объект Objective C, соответствующий протоколу NSObject.

Вам нужно будет создать промежуточный протокол (или «суб-протокол»), который расширяет протокол NSObject:

@protocol ExtendedNSObject <NSObject>
- (void)performInvocationOnMainThread:(NSInvocation *)invocation waitUntilDone:(BOOL)waitForMainThread;
@end

Тогда ваш протокол делегата расширит этот протокол:

@protocol MyDelegateProtocol <ExtendedNSObject>
- (void)myDelegateProtocolMethod;
@end

Если я не ошибаюсь , вы можете сохранить существующую реализацию NSObject (MyCategory), и они будут хорошо играть вместе.

3 голосов
/ 17 мая 2011

когда передаете / ожидаете этот тип, квалифицируйте его так:

- (void)race:(NSObject<MyDelegateProtocol>*)arg;
...