Наблюдение значения ключа для объекта протокола: предупреждения компилятора на addObserver: - PullRequest
10 голосов
/ 12 апреля 2009

У меня есть простой протокол со свойством:

@protocol StopsSource <NSObject>
@property (retain,readonly) NSArray * stops;
@end

Я добавляю наблюдателя значения ключа в другом месте, чтобы прослушать изменения в свойстве "stop":

id<StopsSource> source = ...
[source addObserver:self
         forKeyPath:@"stops"
            options:NSKeyValueObservingOptionNew
            context:nil];

Код работает, как и ожидалось, в том случае, если я изменяю свойство "stop", я получаю события Наблюдение за ValueForKeyPath. Настоящим раздражением является предупреждение компилятора о вызове addObserver:

warning: '-addObserver:forKeyPath:options:context:' not found in protocol(s)

Метод addObserver определен в категории для NSObject:

@interface NSObject(NSKeyValueObserverRegistration)

Есть ли способ заставить XCode сбросить это предупреждение? Насколько я понимаю, протоколы не могут принимать категории, поэтому я не уверен, как включить методы NSKeyValueObserverRegistration в мой протокол, если не считать копирования объявлений в сам протокол, что выглядит как хак.

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

Ответы [ 2 ]

13 голосов
/ 12 апреля 2009

Настоящим раздражением является предупреждение компилятора при вызове addObserver:

warning: '-addObserver:forKeyPath:options:context:' not found in protocol(s)

Метод addObserver определен в категории для NSObject:

@interface NSObject(NSKeyValueObserverRegistration)

Есть ли способ заставить XCode сбросить это предупреждение?

Xcode (строчная буква c) просто показывает вам предупреждение; это GCC, компилятор, который в первую очередь выдает предупреждение.

Вы путаете класс NSObject с протоколом NSObject. Класс NSObject, в частности, соответствует протоколу NSObject, но протоколы не имеют своего отношения к классам. Ваш протокол StopsSource, являющийся протоколом, наследуется от протокола NSObject, а не от класса NSObject.

Ваше объявление охватывает только эти два протокола, а не какой-либо конкретный класс, поэтому оно не включает ничего, кроме тех протоколов, которые может реализовать класс NSObject (например, KVO). Вот почему вы получаете предупреждение.

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

NSObject <StopsSource> *source = …;
0 голосов
/ 12 апреля 2009

Я думаю, вы можете запутаться в том, что делает протокол; он просто определяет набор операций, которые могут быть реализованы другим классом.

Единственное, что в вашем протоколе - это свойство.

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

@interface YourClass : NSObject <StopSource> {
    // etc
@end
...