[英]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):
Selector 方法必須暴露給@objc 才能工作,所以根據我們的例子:
@objc func aSelector() { //do work here }
我將通知放在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的回答,我已經想通了
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.