通知观察者多次调用,即使观察者被移除

Posted

技术标签:

【中文标题】通知观察者多次调用,即使观察者被移除【英文标题】:Notification observer called multiple times even though the observer is removed 【发布时间】:2017-09-27 10:09:06 【问题描述】:

当应用程序处于后台模式或手机处于睡眠状态并收到 VoIP 推送时,AppDelagte 中的以下函数会引导用户(到应用程序中的 UserTableViewController)并发布通知。

UserTableViewController 的 viewDidLoad 中的通知观察者观察通知并调用 func simulateMyIncomingCallFromNotification

我注意到,当我第二次发送 VoIP 推送时,func simulateMyIncomingCallFromNotification 被调用了两次,第三次调用了三次,以此类推。如何避免多次调用?

其他 SO 答案,建议删除通知观察者,我什至在设置之前就这样做了,正如您在下面的扩展中看到的那样,但这似乎并不能解决我的问题。

我该如何解决这个问题?

在 AppDelegate 中:

func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, forType type: PKPushType) 

 let storyboard = UIStoryboard(name: "User", bundle: nil)

 VC = storyboard.instantiateViewController(withIdentifier: "UserTableViewController") as! UserTableViewController

 self.window = UIWindow(frame: UIScreen.main.bounds)
        self.window?.rootViewController = VC
        self.window?.makeKeyAndVisible()


NotificationCenter.default.post(name: Notification.Name("didReceiveIncomingVoipPush"), object: nil, userInfo: payloadDict)

在 UserTableViewController 中

extension NotificationCenter 
    func setObserver(_ observer: AnyObject, selector: Selector, name: NSNotification.Name, object: AnyObject?) 
        print("NotificationCenter.default before: \(NotificationCenter.default)")
        NotificationCenter.default.removeObserver(observer, name: name, object: object)
        NotificationCenter.default.addObserver(observer, selector: selector, name: name, object: object)
        print("NotificationCenter.default after: \(NotificationCenter.default)")
    


fun viewDidLoad()

NotificationCenter.default.setObserver(self, selector: #selector(self.simulateMyIncomingCallFromNotification(notification:)), name: Notification.Name("didReceiveIncomingVoipPush"), object: nil)


【问题讨论】:

感谢您提出带有“即使”子句的问题。现货:) 【参考方案1】:

Apple 建议观察者应在 viewWillAppear 注册并在 viewWillDissapear 取消注册。

你可以这样试试吗。

【讨论】:

【参考方案2】:

多次调用通知可能是因为您的控制器没有被取消初始化,并且每次您向该控制器的新实例添加新的观察者时。 你可以做什么:

在该方法上添加断点并尝试print(self) 并查看多次调用的地址。

或者只是添加

 deinit() 
    print(self)
 

并检查该类是否被取消初始化。

如果不是这样,您可以尝试@Himanth 解决方案。

【讨论】:

Add breakpoint or deinit() on that method 使用哪种方法? 被多次调用的方法simulateMyIncomingCallFromNotification【参考方案3】:

在我的情况下,Notification 正在调用 次数 我出现在同一个屏幕上,这是触发 same action X numberofTime i '我进入屏幕。所以我在viewWillDisappear 中删除了Notification 观察者,这实际上是有效的,并且在同一屏幕中停止了多次触发的动作/方法

感谢Himanth的回答让我明白了

Swift4

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)
      
    

【讨论】:

以上是关于通知观察者多次调用,即使观察者被移除的主要内容,如果未能解决你的问题,请参考以下文章

被移除的通知

标签栏(视图控制器)中多次调用ios的通知中心方法方法?如何删除观察者?

NSNotificatinonCenter iOS9以后不再需要移除观察者-备忘

观察者模式

观察者模式

iOS NSNotificationCenter 移除通知带来的crash