2012-08-11 165 views
23

在用於註冊關鍵值通知的以下方法中,上下文參數有什麼用處。文件只是將其表示爲任意數據。關鍵值觀察中的上下文參數的重要性

addObserver:self forKeyPath:@"selectedIndex" options:NSKeyValueObservingOptionNew context:nil 

有人可以提供一些線索什麼是其背後的目的...

感謝

+0

可能重複(http://stackoverflow.com/questions/1625575/parameters-from-observevalueforkeypathofobjectchangecontext) – 2012-08-11 19:06:23

回答

73

我希望這個解釋是不是太過抽象理解。

假設您創建了一個類MyViewController,它是UIViewController的一個子類。您沒有源代碼UIViewController

現在您決定讓MyViewController使用KVO觀察對self.viewcenter財產的更改。所以,你正式加入自己作爲觀察員:

- (void)viewWillAppear:(BOOL)animated { 
    [super viewWillAppear:animated]; 
    [self.view addObserver:self forKeyPath:@"center" options:0 context:NULL]; 
} 

- (void)viewDidDisappear:(BOOL)animated { 
    [self.view removeObserver:self forKeyPath:@"center"]; 
    [super viewDidDisappear:animated]; 
} 

這裏的問題是,你不知道,如果UIViewController也將自己註冊爲self.viewcenter的觀察員。如果是這樣,那麼你可能有兩個問題:

  1. 當視圖的中心改變時,你可能會被調用兩次。
  2. 當您以觀察者身份離開自己時,您可能還會刪除UIViewController的KVO註冊。

您需要一種方法將自己註冊爲與UIViewController的KVO註冊不同的觀察者。這就是context的論點。你需要傳遞一個值爲context,你絕對相信UIViewController而不是使用作爲context參數。當您取消註冊時,您再次使用相同的context,以便您只刪除註冊,而不是UIViewController的註冊。在observeValueForKeyPath:ofObject:change:context:方法中,您需要檢查context以查看該消息是針對您還是針對您的超類。

確保使用context的其中一種方法是,在MyViewController.m中創建一個static變量。當你註冊和註銷,像這樣使用它:在您的observeValueForKeyPath:...方法

static int kCenterContext; 

- (void)viewWillAppear:(BOOL)animated { 
    [super viewWillAppear:animated]; 
    [self.view addObserver:self forKeyPath:@"center" options:0 context:&kCenterContext]; 
} 

- (void)viewDidDisappear:(BOOL)animated { 
    [self.view removeObserver:self forKeyPath:@"center" context:&kCenterContext]; 
    [super viewDidDisappear:animated]; 
} 

然後,檢查它像這樣:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object 
    change:(NSDictionary *)change context:(void *)context 
{ 
    if (context == &kCenterContext) { 
     // This message is for me. Handle it. 
     [self viewCenterDidChange]; 
     // Do not pass it on to super! 
    } else { 
     // This message is not for me; pass it on to super. 
     [super observeValueForKeyPath:keyPath ofObject:object 
      change:change context:context]; 
    } 
} 

現在你不能保證你的超類的志願干擾,如果它做任何。如果有人使用也使用KVO的MyViewController的子類,它不會干擾您的KVO。

還要注意,您可以爲您觀察的每個關鍵路徑使用不同的上下文。然後,當系統通知您有更改時,您可以檢查上下文而不是檢查關鍵路徑。測試指針相等性比檢查字符串相等性要快一些。例如:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object 
    change:(NSDictionary *)change context:(void *)context 
{ 
    if (context == &kCenterContext) { 
     [self viewCenterDidChange]; 
     // Do not pass it on to super! 
    } else if (context == &kBackgroundColorContext) { 
     [self viewBackgroundDidChange]; 
     // Do not pass it on to super! 
    } else if (context == &kAlphaContext) { 
     [self viewAlphaDidChange]; 
     // Do not pass it on to super! 
    } else { 
     // This message is not for me; pass it on to super. 
     [super observeValueForKeyPath:keyPath ofObject:object 
      change:change context:context]; 
    } 
} 
[參數從observeValueForKeyPath:ofObject變化:背景:]的
+0

感謝很多關於你的詳細解釋真的很感激。一段時間以來,我一直困惑着爲什麼這個參數很重要,並且你的回答能夠澄清它。 :) – rustylepord 2012-08-12 08:19:24

+0

你好我可以使用上下文來設置一些對象,稍後當通知來檢索它時o根據存儲在上下文中的值執行一些特定的任務。 – Sandeep 2012-11-26 15:06:34

+9

+1精彩的解釋。 (一個單獨的警告:'UIView'的屬性不符合KVO,不能觀察'view.center'。) – 2013-10-08 15:48:59