簡體   English   中英

如何阻止 NSNotification 中的觀察者調用兩次?

[英]How to stop the Observer in NSNotification to called twice?

我有一個NSNotification的觀察者,它被調用了兩次。 我不知道該怎么辦。

我用谷歌搜索但沒有找到解決方案。

[[NSNotificationCenter defaultCenter] addObserver:self
     selector:@selector(connectedToServer:) name:@"ConnectedToServer" object:nil];

- (void)connectedToServer:(NSNotification*)notification {

    [[NSNotificationCenter defaultCenter] postNotificationName:@"SendMessageToServer" object:message];
}

解決方案 1:首先要檢查通知本身是否發布了兩次。

解決方案 2:即使通知僅發布一次,該操作也會被調用與您為通知添加觀察者的次數相同(無論通知是否相同)。 例如,以下兩行將針對同一個通知( aSelector )注冊觀察者( self )兩次。

[[NSNotificationCenter defaultCenter] addObserver:self selector:aSelector name:aName object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:aSelector name:aName object:nil];

您必須找到第二次添加觀察者的位置,然后將其刪除。 還要確保添加觀察者的代碼沒有被調用兩次。

解決方案 3:如果您不確定是否已經添加了觀察者,您可以簡單地執行以下操作。 這將確保觀察者只添加一次。

[[NSNotificationCenter defaultCenter] removeObserver:self name:aName object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:aSelector name:aName object:nil];

如果您的addObserver方法運行多次,它將創建多個觀察者。 我的問題是我以某種方式將我的觀察者放在viewWillAppear ,它在我發布通知之前出現了多次,這導致我的觀察者被多次調用。

雖然 EmptyStack 的第三個解決方案有效,但您的觀察者被調用兩次是有原因的,因此通過找到它,您可以防止不必要的代碼行,而不是刪除和添加相同的觀察者。

我建議將您的觀察者放在viewDidLoad以避免像我遇到的那樣的簡單錯誤。

嘗試在 viewWillDisappear 方法中 removeObserver :

-(void)viewWillDisappear:(BOOL)animated{

[[NSNotificationCenter defaultCenter] removeObserver:self name:@"startAnimating" object:nil]; }

嘗試在[[NSNotificationCenter defaultCenter] addObserver:self selector:aSelector name:aName object:nil];上設置斷點[[NSNotificationCenter defaultCenter] addObserver:self selector:aSelector name:aName object:nil]; 並檢查它是否被多次調用。

對於那些在 Swift 2.2 及更高版本中尋找解決方案並像我一樣遇到這個問題的人,您可以創建一個擴展如下:

import Foundation

extension NSNotificationCenter {
  func setObserver(observer: AnyObject, selector: Selector, name: String?, object: AnyObject?) {
    NSNotificationCenter.defaultCenter().removeObserver(observer, name: name, object: object)
    NSNotificationCenter.defaultCenter().addObserver(observer, selector: selector, name: name, object: object)
  }
}

您可以按如下方式調用此方法:

NSNotificationCenter.defaultCenter().setObserver(self, selector: #selector(methodName), name: "name", object: nil)

如果存在,擴展將處理移除先前觀察者。 即使沒有先前的觀察者在場,此代碼也不會崩潰。

我有同一個類的兩個實例,我花了一些時間才意識到通知不是在該類的一個實例中運行兩次,而是在兩個實例中運行兩次。

我在基於文檔的應用程序中使用通知。 每個文檔的觀察者類(一個 ViewController)都捕捉到了通知。 打開兩個文件,函數被調用了兩次。 三個文件打開......你明白了。

要限制接收通知的人,您可以指定您對特定對象感興趣,但這有一個轉折點:該對象需要是類對象的相同實例; 你不能簡單地比較一個值; 所以 UUID 沒有匹配,而是一個實例

class DocumentID {
    var id = UUID()
}

工作正常。 將此從您的 Document 注入到每個發送或接收通知的類,並且您將通知限制在您的文檔中。

Swift 5+ 解決方案

NotificationCenter.default.removeObserver(self, name: aName, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(aSelector), name: aName, object: nil)

一些提示(一對夫婦總是意味着 2):

  1. Selector 方法必須暴露給@objc 才能工作,所以根據我們的例子:

     @objc func aSelector() { //do work here }
  1. 我將通知放在init()deinit()並使用單例來避免重復它們,如下所示:

     init() { NotificationCenter.default.addObserver(self, selector: #selector(aSelector), name: aName, object: nil) //add any other notifications here } deinit() { NotificationCenter.default.removeObserver(self) }

在我的情況下, Notification正在調用我出現在同一屏幕上的時間,這會導致觸發相同的操作X numberofTime 我進入 screen 所以我在viewWillDisappear刪除了Notification觀察者,它實際上是有效的,並在同一個屏幕中停止了多次觸發的動作/方法

感謝Himanth的回答,我已經想通了

  • 斯威夫特4

addObserver

 override func viewDidLoad(){
       super.viewDidLoad()

      NotificationCenter.default.addObserver(self, selector: #selector(self.yourNotificationAction(notification:)), name: Notification.Name("yourNotificationName"), object: nil)

}

屏幕消失時removeObserver

 override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        
        NotificationCenter.default.removeObserver(self, name: Notification.Name("yourNotificationName"), object: nil)
      
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM