【问题标题】:declare NotificationCenter.default.addObserver [swift]声明 NotificationCenter.default.addObserver [swift]
【发布时间】:2020-02-25 15:53:27
【问题描述】:

如何在 Swift 中将观察者添加到通知中心?

这样做:

override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(ReloadData), name: NSNotification.Name(rawValue: "ReloadData"), object: nil)

}
@objc func ReloadData(notification: NSNotification) {
        // func
        print ("FUNC TEST")
    }

但是每次控制器关闭/打开(在标签栏的标签之间切换)时,都会添加一个新的侦听器。 当我打电话时

print ("Call Notif")
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "ReloadData"), object: nil)

"func ReloadData" 被多次调用。控制台:

Call Notif
FUNC TEST
FUNC TEST

将再次在标签栏的标签之间切换。

Call Notif
FUNC TEST
FUNC TEST
FUNC TEST

我怎么能只答应你一次?

【问题讨论】:

  • 通过NotificationCenter.default.removeObserver(self) 取消订阅viewWillDisappear 方法并订阅viewWillAppearThis is actually a duplicate question
  • 阿列克谢,是的!但我需要观察者留下来。我不希望它被删除。我想要一份。
  • 虽然上面的评论解决了您的问题的可见部分,但真正的问题是 您在内存中加载了该控制器的多个实例。所以你应该明白为什么会发生这种情况。这肯定是内存泄漏/糟糕的设计。
  • 你订阅了你的 viewControllers 超类中的通知吗?因为 UITableViewController 的控制器只创建一次(viewDidLoad 在创建时被调用一次)并且在它们的父级(tabbarcontroller)被释放时被释放。

标签: ios swift notificationcenter


【解决方案1】:

我的情况和你类似。阅读 https://stackoverflow.com/a/60399071/14414215https://stackoverflow.com/a/51745479/1040347 并尝试后,在我使用 UITabBarController 设计将数据传递到不同选项卡的特定场景中,它对我不起作用。

Tab1 是主屏幕 Tab2 是锻炼库(用户选择数据)

然后使用 TabBarController 作为中间 https://stackoverflow.com/a/65499693/14414215 将数据从 Tab2 传递到 Tab1。在 Tab1 中添加 removeObserver 时

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    NotificationCenter.default.removeObserver(self)
}

这将导致数据无法从 Tab2 传递到 Tab1,因为每当用户从 Tab1 移动到 Tab2 时都会取消订阅通知。

我也尝试将 removeObserver 添加到 TabBarController 中,但这没有做任何事情。

最后,起作用的是从 objc 中取消订阅,例如:

在 Tab1 中:

override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(ReloadData), name: NSNotification.Name(rawValue: "ReloadData"), object: nil)

}
@objc func ReloadData(notification: NSNotification) {
        // func
        print ("FUNC TEST")
        NotificationCenter.default.removeObserver(self). // Adding it here works and its then only called ONCE
    }

【讨论】:

    【解决方案2】:

    不管你喜不喜欢,最简单的解决方案就是利用控制器的生命周期。

    1. 订阅控制器每次出现或加载的通知。
    2. 删除每次deinit 或控制器消失的通知。

      override func viewWillAppear(_ animated: Bool) {
          super.viewWillAppear(animated)
      
          NotificationCenter.default.post(name: NSNotification.Name(rawValue: "ReloadData"), object: nil)
      
      }
      
      override func viewWillDisappear(_ animated: Bool) {
          super.viewWillDisappear(animated)
      
          NotificationCenter.default.removeObserver(self)
      }
      

    如果您的每个控制器都有一个基类,您可以将removeObserver() 放在该基类中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-26
      • 1970-01-01
      • 2015-03-27
      • 2017-11-16
      • 2015-02-15
      • 1970-01-01
      • 1970-01-01
      • 2014-08-19
      相关资源
      最近更新 更多