You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

iOS通知中心重复触发问题:多次进入视图后savingAll重复执行

问题原因与解决方案

这个问题的核心是你重复注册了通知观察者,且没有在视图控制器生命周期结束时移除它们,具体逻辑是这样的:

  • 首次进入视图时,你调用NotificationCenter.default.addObserver(...)注册了一个观察者,此时App最小化触发通知,savingAll只会执行1次。
  • 当你离开这个视图(比如返回上一页或关闭弹窗),如果没有移除这个观察者,NotificationCenter会一直持有这个视图控制器的引用,导致它无法被销毁。
  • 当你再次返回这个视图时,代码又会执行一次addObserver,此时NotificationCenter里就存在两个指向当前视图控制器的观察者。
  • 之后每次触发AppMinimilised通知,所有注册的观察者都会响应,所以saingAll的执行次数会随着你返回视图的次数递增。

解决方法

1. 在视图销毁时手动移除观察者

在你的视图控制器中添加deinit方法,移除对应的通知观察者,确保视图控制器被销毁时清理掉注册的观察者:

deinit {
    NotificationCenter.default.removeObserver(self, name: Notification.Name("AppMinimilised"), object: nil)
}

这样每次视图控制器被销毁时,都会把自己注册的这个通知观察者移除,从根源避免重复注册。

2. 使用Block式通知注册(推荐)

这种方式会返回一个令牌对象,你可以持有它来管理观察者的生命周期,而且能避免selector方式可能出现的方法匹配问题,同时配合弱引用避免内存泄漏:

// 定义属性持有观察者令牌
private var appMinimisedObserver: NSObjectProtocol?

override func viewDidLoad() {
    super.viewDidLoad()
    // 注册通知,使用weak self避免强引用循环
    appMinimisedObserver = NotificationCenter.default.addObserver(forName: Notification.Name("AppMinimilised"), object: nil, queue: .main) { [weak self] _ in
        self?.savingAll()
    }
}

deinit {
    // 移除观察者
    if let observer = appMinimisedObserver {
        NotificationCenter.default.removeObserver(observer)
    }
}

当视图控制器被销毁时,deinit会触发并移除对应的观察者,不会留下多余的注册项。

3. 确保只注册一次观察者

如果你的视图控制器是常驻内存的(比如TabBar的子页面),可以把注册代码放在viewDidLoad中(viewDidLoad只会在视图控制器初始化时执行一次),而不是viewWillAppearviewDidAppear,这样就不会重复注册了。


内容的提问来源于stack exchange,提问作者Damian Talaga

火山引擎 最新活动