2012-02-10 64 views
37

當使用addObserver:forKeyPath:options:context:觀察對象上的值時,最終您需要在該對象上調用removeObserver:forKeyPath:以稍後進行清理。但在此之前,是否可以檢查一個對象是否真的在觀察該屬性?KVO - 如何檢查對象是否是觀察者?

我試圖確保在我的代碼中,一個對象只在需要時纔會被刪除,但有些情況下觀察者可能會嘗試刪除自己兩次。我正在努力防止這種情況發生,但爲防萬一,我一直在試圖弄清楚是否有辦法檢查我的代碼是否實際上是某個事物的觀察者。在NSKeyValueObserving協議

+0

KVO,因爲它有一個相當粗糙的API。有些庫可以簡化它的使用,甚至允許你爲了方便而使用塊。詳情請查閱http://thirdcog.eu/pwcblocks/#goodies。我也有我自己的實現能夠自動刪除觀察員,當任何對象被釋放。它尚未在實際應用中進行過測試,但您可能還是要仔細看看。在GitHub上搜索'tastykvo'。 – 2012-02-10 17:46:33

回答

43

[...]是否有可能檢查一個對象是否實際上正在觀察該屬性 屬性?

號當志願打交道,你應該始終牢記以下模型:

當建立一個觀察你是負責清除,準確的觀察。觀察是通過它的上下文來確定的 - 因此,上下文必須是獨特的。當接收到通知時(並且在Lion中,當移除觀察者時),您應該始終測試上下文,而不是路徑。

處理觀察對象是,以去除,並在觀察對象的二傳手建立觀測的最佳實踐:

static int fooObservanceContext; 

- (void)setFoo:(Foo *)foo 
{ 
    [_foo removeObserver:self forKeyPath:@"bar" context:&fooObservanceContext]; 

    _foo = foo; // or whatever ownership handling is needed. 

    [foo addObserver:self forKeyPath:@"bar" options:0 context:&fooObservanceContext]; 
} 

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{ 
    if (context == &fooObservanceContext) { 
     // handle change 
    } else { 
     // not my observer callback 
     [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; 
    } 
} 

- (void)dealloc 
{ 
    self.foo = nil; // removes observer 
} 

當使用志願,你必須確保這兩個對象,觀察者和observee,只要觀察到位,他們就活着。

當添加一個觀察,你必須平衡這與一個刪除相同的觀察。不要假設,你是唯一使用KVO的人。框架類可能會將KVO用於自己的目的,因此請始終檢查回調中的上下文。

我想指出的最後一個問題:觀察到的屬性必須符合KVO。 You can't just observe anything

+0

您是否需要將fooObservanceContext設置爲任何內容,或者在添加觀察者時需要注意? – jrturton 2012-02-10 17:59:58

+2

它會自動初始化爲零,但在這種情況下,它僅用於其地址。我們需要一個獨特的'context'值。由於我們不知道其他人用作上下文的情況,因此這似乎是創建以前不太可能使用的值的一種很好的方式。 – 2012-02-10 18:04:08

+0

好的,所以它有一個地址,因爲它是靜態的,這就是你使用&?傳遞的東西。我對事物的所有方面都不太熱衷,感謝解釋! – jrturton 2012-02-10 18:06:03

25

部分是這樣的:

- (void *)observationInfo 

應列出觀察員。

編輯 僅用於調試。

+1

我只是寫了一個答案,該列表顯式不可用,因爲'observationInfo'被記錄爲返回一個不透明的指針(實際上,它可能是也可能不是一個對象)。這聽起來準確嗎? – Tommy 2012-02-10 17:34:56

+0

@Tommy最有可能的是準確的。我只是在文檔中寫道:「返回一個標識所有觀察者信息的指針」。我懷疑你比我更瞭解這一點。 – Rayfleck 2012-02-10 17:42:12

+3

你不能在生產代碼中使用它,但在調試器中它非常有用:鍵入'po [observedObject observationInfo]',你可以很好地瞭解觀察者和關鍵路徑。 – 2012-02-10 17:43:47