2015-06-23 59 views
2

我一直在試圖解決NSOperation子類中的一個問題,我覺得它可能與我們的KVO的手動更改通知有關。所有我檢查的來源似乎做更新的NSOperation狀態時的情況如下:多個KVO鍵:爲什麼要調用willChangeValueForKey:在didChangeValueForKey之前兩次:?

[self willChangeValueForKey:@"isExecuting"]; 
[self willChangeValueForKey:@"isFinished"]; 
_isExecuting = NO; 
_isFinished = YES; 
[self didChangeValueForKey:@"isFinished"]; 
[self didChangeValueForKey:@"isExecuting"]; 

相反,我們一直在做這樣的:

[self willChangeValueForKey:@"isExecuting"]; 
_isExecuting = NO; 
[self didChangeValueForKey:@"isExecuting"]; 

[self willChangeValueForKey:@"isFinished"]; 
_isFinished = YES; 
[self didChangeValueForKey:@"isFinished"]; 

任何人能告訴我,爲什麼前似乎是這樣做的推薦方式?

似乎蘋果的KVO文檔也推薦了第一種方法。 (https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/KeyValueObserving/Articles/KVOCompliance.html#//apple_ref/doc/uid/20002178-SW3)/

回答

0

原因是,從概念上講,操作會將兩個狀態一起改變,只有在內部狀態已經更新兩個屬性後纔會通知觀察者,因此,處理通知時,觀察者看到一致的狀態

如果你這樣做:

[self willChangeValueForKey:@"isExecuting"]; 
_isExecuting = NO; 
[self didChangeValueForKey:@"isExecuting"]; 

那麼觀察員將得到該isExecuting性質改變通知didChange...通話過程中如果您在操作性質的。處理程序,他們合作(isExecuting返回NO)但還沒有完成(isFinished仍然返回NO)。這沒有意義。觀察員可以做一些奇怪的事情。

+0

有趣。似乎這種模式需要了解NSOperation內部觀察者如何處理狀態變化。你知道有沒有關於這方面的進一步文件? – fyell

+0

您是指操作隊列如何觀察其操作?這不一定就是這個。其他東西可以觀察操作屬性。我正在寫關於一般情況。不,我沒有關於隊列如何觀察他們的操作並對這些變化作出響應的進一步文檔。 –

+0

不在NSOperationQueue級別。我假設當一個NSOperation被初始化時,它也會自己建立KVO。我做了這個假設,因爲這個調用我在堆棧跟蹤崩潰中看到'[__NSOperationInternal _observeValueForKeyPath:ofObject:changeKind:oldValue:newValue:indexes:context:]'。 – fyell

0

我實現的NSOperation不按模式

[self willChangeValueForKey:@"isExecuting"]; 
[self willChangeValueForKey:@"isFinished"]; 
_isExecuting = NO; 
_isFinished = YES; 
[self didChangeValueForKey:@"isFinished"]; 
[self didChangeValueForKey:@"isExecuting"]; 

,而不是通過簡單地做

self.executing = NO; 
self.finished = YES; 

..沒有問題使用NSOperationQueues時(永無止境的操作等)。看來NSOperationQueue只會偵聽'IsFinished'來確定NSOperation是否真正完成。這個其他答案更好地解釋。

NSOperation KVO isFinished

相關問題