2010-07-28 189 views
1

我有一個NSArrayController鏈接到核心數據對象,設置爲自動重新排列內容並由謂詞過濾。一切都很好,直到我試圖取消關係並分配另一個關係。在這一點上,我的應用程序崩潰,我收到以下錯誤:KVO問題「無法刪除觀察者」

Cannot remove an observer for the key path "career.type" from Object, most likely because the value for the key "career" has changed without an appropriate KVO notification being sent. Check the KVO-compliance of the Person class.

從周圍窺探,似乎有我的NSArrayController的設置爲自動重新編排內容導致此問題。但我試圖解決問題,而不必手動重新排列NSArrayController。這裏是一個的觸發錯誤的僞代碼:

object.career = nil; 
object.field = (Field *)item; 

這裏是我的NSArrayController的使用謂詞:

(career != NIL && career == %@) || (field != NIL && field == %@) 

凡%@對於這兩種情況下是一個CoreData對象。

基本上,它看起來好像NSArrayController有一個爲object.career.type設置的觀察者,並且當該觀察者被自動刪除時取消關係會導致問題。所以我想知道如果我以錯誤的方式去解決這個問題?我是否應該抓取該對象的副本,將其從MOC中刪除並重新插入,並設置相應的nil和field設置?

如何正確通知觀察者該類型已被取消?請注意,這裏提到的所有屬性和關係使用符合vanilla KVO的getter/setter。

回答

4

From apples documentation

故障和KVO通知

當核心數據變成對象插入到故障時,鍵 - 值觀察(KVO)更改通知(參見鍵 - 值觀察編程指南)被用於發送該對象的屬性。如果您正在觀察轉換爲故障的對象的屬性,並隨後實現故障,則會收到其值實際上未發生更改的屬性的更改通知。

雖然從您的角度來看,這些值在語義上沒有變化,但是隨着對象的物化,內存中的文字字節也在變化。鍵值觀察機制要求Core Data在從指針比較的角度考慮值發生變化時發出通知。 KVO需要這些通知來跟蹤關鍵路徑和相關對象的變化。


所以基本上你會得到一個通知,告訴你即使不是這樣也會有變化。所以你必須檢查對象是否成爲故障。然後刪除舊的觀察員,並添加一個新的相同的路徑...

對我來說,這個工作(示例代碼):

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

    if ([keyPath isEqualToString:@"pageIndex"]) { 

     // basically remove the observer from the fault object and assign the new 
     if([object isFault]) { 
      [object removeObserver:self forKeyPath:@"pageIndex"]; 
      [the_current_instance_returned_by_core_data addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionOld context:NULL]; 
     } 

     // do whatever you want to do on change... 

    } 
}