我正在使用以下函数在nsoperationqueue中的操作完成后通知我的应用程序,以便我可以安排依赖于操作结果的任务。我正在使用:
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
if([keyPath isEqual:@"isFinished"] && _operation == object)
{
NSLog(@"Our Thread Finished!");
[_operation removeObserver:self forKeyPath:@"isFinished"];
[self performSelectorOnMainThread:@selector(showDialog) withObject:nil waitUntilDone:YES];
}
}
我的问题是,由于分配给这些操作的任务主要是解析数据,如果我尝试点击其他按钮或基本上做了导致操作的事情,我会得到以下异常:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '<Settings: 0x21b970>: An -observeValueForKeyPath:ofObject:change:context: message was received but not handled.
Key path: isFinished
我完全理解,因为我尝试在主线程上做其他事情,因为调用主线程:
[self performSelectorOnMainThread:@selector(showDialog) withObject:nil waitUntilDone:YES];
无法执行。但是这个问题的解决方案是什么,因为我希望两者都允许用户在发出请求后执行任何操作,并在完成分配给操作的任务后执行计划的操作。
真的有可能吗?
提前完成。
答案 0 :(得分:0)
如果您需要Mac OS X 10.6 Snow Leopard或(我认为)iPhone OS 3.0,您可以完全避免使用KVO。只需为要在主线程上完成的工作创建另一个操作,添加它需要作为依赖项执行的操作,然后将主线程操作放在主队列上:
NSBlockOperration *mainThreadOp = [NSBlockOperation blockOperationWithBlock:^{
[self showDialog];
}];
[mainThreadOp addDependency:backgroundOp];
[[NSOperationQueue mainQueue] addOperation:mainThreadOp];
NSOperation支持不同队列上的操作之间的依赖关系。注意不要让不同队列上的操作相互依赖,因为这会导致死锁。
答案 1 :(得分:0)
您遇到此问题的原因是您没有使用context
指针。
添加或删除观察者时,传递上下文指针。在observeValueForKeyPath:ofObject:change:context:
中,检查上下文点以确保传递的观察属于您。如果没有,请致电超级。可以使用self作为上下文点,或者可以使用静态字符串的地址等。
这是一个例子:
[sample addObserver:self forKeyPath:@"finished" options:[self observationOptions] context:(void *)self];
- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (context == (__bridge void *)self){
if ([keyPath isEqualToString:@"finished"]){
// Handle the change here.
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
[sample removeObserver:self forKeyPath:@"finished" context:(void *)self];
由于您的代码无法将其中一个通知传递给observeValueForKeyPath:ofObject:change:context:
中的超级通知,因此该通知已进入,但从未发布过。这就是你遇到这个例外的原因。
很遗憾,IntarWebs上提供的许多Key-Value Observing示例都没有正确执行此操作和/或将NULL
作为上下文指针传递(即使是Apple的文档也这样做)。