문제

I have a public variable in my Objective-C++ AppDelegate called stepsCompleted, so I access it in my table view controller with [AppDelegate instance]->stepsCompleted.

I want my table view controller to tell me when the value of that variable has changed, so I do the following in the initWithCoder: method that I know is being called:

[self addObserver:self forKeyPath:@"[AppDelegate instance]->stepsCompleted" options:0 context:NULL];

However, despite me changing stepsCompleted constantly in the AppDelegate, my method:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {

}

Is never called.

What exactly am I doing wrong?

도움이 되었습니까?

해결책

There are different problems with your code. First of all, Key-Value Observing is a mechanism to observe properties of an object. It does not work with instance variables. So you should declare "stepsCompleted" as a property of the application delegate instead of an instance variable:

@property (nonatomic) int stepsCompleted;

and set its value through the property accessor methods, e.g.

[AppDelegate instance].stepsCompleted = newValue;

Next, "[AppDelegate instance]->c" is not a key path, and you have to specify at least one observing option, e.g. NSKeyValueObservingOptionNew.

To observe the "stepsCompleted" property of [AppDelegate instance], it should be

[[AppDelegate instance] addObserver:self 
                         forKeyPath:@"stepsCompleted"
                            options:NSKeyValueObservingOptionNew
                            context:NULL];

다른 팁

Although it’s the quickest and easiest way, you don’t really need to declare an @property to use KVO, you just need to make sure that before you call willChange and didChange for the property correctly, and a way to access it.

For instance, in the most manual case, you could implement stepsCompleted like this:

@implementation SomeClass {
   int _stepsCompleted;
}

- (void)setStepsCompleted:(int)stepsCompleted;
{
    [self willChangeValueForKey:@“stepsCompleted”];
    _stepsCompleted = stepsCompleted;
    [self didChangeValueForKey:@“stepsCompleted”];
}

- (int)stepsCompleted;
{
    return _stepsCompleted;
}

@end

Then if you observed the keyPath “stepsCompleted” on “someObject" you would get called when it changed, assuming you ONLY ever changed it by using its setter, for example via:

[self stepsCompleted:10];

But since Apple introduced properties, the above can be shortened to the exactly equivalent:

self.stepsCompleted = 10;

But that’s still a whole lot of code for the setter and getter, and you don’t have to write all that, because Apple did a couple cool things in the last several years. One is the @property notation, which basically writes the above set/get code for you (with some extra good stuff thrown in). So now you can just put in your .h file:

@property int stepsCompleted;

And those two methods will be written for you. As long as you make sure you ONLY use the dot-notation or call the setter directly, KVO will work.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top