声明 NotificationCenter.default.addObserver [swift]

Posted

技术标签:

【中文标题】声明 NotificationCenter.default.addObserver [swift]【英文标题】:declare 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 方法并订阅viewWillAppear。 This is actually a duplicate question 这能回答你的问题吗? Swift NotificationCenter remove observer quickest way 阿列克谢,是的!但我需要观察者留下来。我不希望它被删除。我想要一份。 虽然上面的评论解决了您的问题的可见部分,但真正的问题是 您在内存中加载了该控制器的多个实例。所以你应该明白为什么会发生这种情况。这肯定是内存泄漏/糟糕的设计。 你订阅了你的 viewControllers 超类中的通知吗?因为 UITableViewController 的控制器只创建一次(viewDidLoad 在创建时被调用一次)并且在它们的父级(tabbarcontroller)被释放时被释放。 【参考方案1】:

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

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

然后使用 TabBarController 作为中间 https://***.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】:

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

    订阅控制器每次出现或加载的通知。

    删除每次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() 放在该基类中。

【讨论】:

以上是关于声明 NotificationCenter.default.addObserver [swift]的主要内容,如果未能解决你的问题,请参考以下文章

javascript中函数声明变量声明以及变量赋值之间的关系与影响

声明那回事儿

Go语言基础之变量声明

C#显式声明隐式声明是怎么定义的

JavaScript 函数声明和变量声明

在C语言中声明和定义的区别?