Новое в Key-Value-Observing; почему я не могу отслеживать значение int в моем AppDelegate?
У меня есть открытая переменная в моем Objective-C++ AppDelegate под названием stepsCompleted
, поэтому я обращаюсь к ней в моем контроллере табличного представления с помощью [AppDelegate instance]->stepsCompleted
.
Я хочу, чтобы мой контроллер табличного представления сообщал мне, когда значение этой переменной изменилось, поэтому я делаю следующее в методе initWithCoder:
, который, как я знаю, вызывается:
[self addObserver:self forKeyPath:@"[AppDelegate instance]->stepsCompleted" options:0 context:NULL];
Однако, несмотря на то, что я постоянно меняю stepsCompleted
в AppDelegate, мой метод:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
}
Никогда не вызывается.
Что именно я делаю не так?
2 ответа:
Существуют различные проблемы с вашим кодом. Прежде всего, наблюдение за ключевыми значениями-это механизм наблюдения свойств объекта. Он не работает с экземпляром переменная. Таким образом, вы должны объявить "stepsCompleted" как свойство делегата приложения вместо переменной экземпляра:
@property (nonatomic) int stepsCompleted;
И установить его значение с помощью методов доступа к свойствам, например
[AppDelegate instance].stepsCompleted = newValue;
Далее,
"[AppDelegate instance]->c"
не является ключевым путем, и вы должны указать хотя бы один параметр наблюдения, например:NSKeyValueObservingOptionNew
.Чтобы наблюдать свойство "stepsCompleted"
[AppDelegate instance]
, оно должно быть[[AppDelegate instance] addObserver:self forKeyPath:@"stepsCompleted" options:NSKeyValueObservingOptionNew context:NULL];
Хотя это самый быстрый и простой способ, вам действительно не нужно объявлять
@property
, чтобы использовать KVO, вам просто нужно убедиться, что перед вызовом willChange и didChange для свойства правильно, и способ доступа к нему.Например, в самом ручном случае вы можете реализовать
stepsCompleted
следующим образом:@implementation SomeClass { int _stepsCompleted; } - (void)setStepsCompleted:(int)stepsCompleted; { [self willChangeValueForKey:@“stepsCompleted”]; _stepsCompleted = stepsCompleted; [self didChangeValueForKey:@“stepsCompleted”]; } - (int)stepsCompleted; { return _stepsCompleted; } @end
Затем, если вы заметили, что ключевой путь "stepsCompleted" на "someObject", вы будете вызваны, когда он изменится, предполагая, что вы когда-либо изменяли его только с помощью его сеттера, например пример через:
[self stepsCompleted:10];
Но поскольку Apple ввела свойства, вышесказанное можно сократить до точно эквивалентного:
self.stepsCompleted = 10;
Но это все еще очень много кода для сеттера и геттера, и вам не нужно писать все это, потому что Apple сделала пару крутых вещей за последние несколько лет. Один из них-это нотация @ property, которая в основном пишет приведенный выше код set / get для вас (с некоторыми дополнительными хорошими вещами). Так что теперь вы можете просто положить в свой .х файл:@property int stepsCompleted;
И этих двух методов будет написана специально для вас. Пока вы уверены, что используете только точечную нотацию или вызываете сеттера напрямую, кво будет работать.