- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
以上兩個函數放在self這個的實現中
[self.inProgressAdder addObserver:self forKeyPath:@"isFinished" options:0 context:&self->_formattedTotal];
[self.inProgressAdder addObserver:self forKeyPath:@"isExecuting" options:0 context:&self->_queue];
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (context == &self->_formattedTotal) {
AdderOperation * op;
// If the operation has finished, call -adderOperationDone: on the main thread to deal
// with the results.
// can be running on any thread
assert([keyPath isEqual:@"isFinished"]);
op = (AdderOperation *) object;
assert([op isKindOfClass:[AdderOperation class]]);
assert([op isFinished]);
fprintf(stderr, "%c %3lu finished\n", CharForCurrentThread(), (unsigned long) op.sequenceNumber);
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"applyResultsFromThread"]) {
[self adderOperationDone:op];
} else {
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"allowStale"]) {
[self performSelectorOnMainThread:@selector(adderOperationDoneWrong:) withObject:op waitUntilDone:NO];
} else {
[self performSelectorOnMainThread:@selector(adderOperationDone:) withObject:op waitUntilDone:NO];
}
}
} else if (context == &self->_queue) {
AdderOperation * op;
// We observe -isExecuting purely for logging purposes.
// can be running on any thread
assert([keyPath isEqual:@"isExecuting"]);
op = (AdderOperation *) object;
assert([op isKindOfClass:[AdderOperation class]]);
if ([op isExecuting]) {
fprintf(stderr, "%c %3lu executing\n", CharForCurrentThread(), (unsigned long) op.sequenceNumber);