ios - NotificationCenter.default.addObserver 不断被 Unwind Segue 调用多次
问题描述
我正在使用 show segue 和 unwind segue 在两个iOS
视图控制器 VC1 和 VC2 之间导航。在viewDidLoad()
VC2 中,我让 VC2 成为观察者。这是我的代码:
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "buzzer updated"), object: nil, queue: OperationQueue.main) { _ in
print("set beeperViewImage")
}
}
每次我使用 unwind segue 从 VC2 回到 VC1时,addObserver()
都会调用一次额外的时间,例如,在第四次返回时segue
addObserver 被调用 4 次;在第五次segue
、五次等。即使应用程序被发送到后台并被调用,也会发生这种行为。它会记住在上一个会话中发生了多少次 segue,并从那里获取计数。
我在 VC1 中多次调用没有问题,这是初始 VC。
我试图在展开 segueing 后将 VC2 设置为 nil。
期待任何指导。
解决方案
这无疑是您的视图控制器没有被释放的情况。也许你有一个强大的参考周期。
例如,考虑这个无害的例子:
extension Notification.Name {
static let buzzer = Notification.Name(rawValue: Bundle.main.bundleIdentifier! + ".buzzer")
}
class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(forName: .buzzer, object: nil, queue: .main) { _ in
self.foo()
}
}
func foo() { ... }
}
如果我然后进入和离开这个视图控制器 3 次,然后单击“调试内存图”按钮,我将看到以下内容:
我可以在左侧面板中看到我的第二个视图控制器的三个实例,如果它们被正确释放,它们就不会出现在那里。当我在该面板中单击其中任何一个时,我可以看到仍然对相关视图控制器具有强烈引用的可视化图表。
在这种情况下,因为我在“Product”»“Scheme”»“Edit Scheme...”»“Run”»“Diagnostics”»“Logging”下打开了“Malloc Stack”功能,所以我可以看到堆栈跟踪最右边的面板,甚至可以单击箭头按钮并转到有问题的代码:
在这个特定的例子中,问题是我(故意地,为了说明的目的)引入了一个持久的强引用,通知中心保持对 的强引用self
,这是由于观察者的关闭而强加的。[weak self]
通过使用该闭包中的模式,这很容易解决:
NotificationCenter.default.addObserver(forName: .buzzer, object: nil, queue: .main) { [weak self] _ in
self?.foo()
}
现在,我不知道这是否是您案例中强引用循环的来源,因为您的代码片段中的代码实际上并未引用self
. 也许您在与我们共享代码片段时简化了代码片段。也许你有一些完全不同的东西来保持对你的视图控制器的引用。
但是通过使用这个“Debug Memory Graph”按钮,你不仅可以(a)确认你的相关视图控制器在内存中确实有多个实例;而且(b)确定是什么建立了这种强有力的参考。从那里,您可以诊断问题的根本原因。但是您问题中的代码不足以产生此问题,但我怀疑某处存在强大的参考周期。
推荐阅读
- python - 如何在列表循环中找到特定位置的最小值和最大值?
- java - 尝试在 tomcat 6 中执行 .war 文件时出现 503 错误
- docker - docker-compose 运行、启动、启动之间的区别
- android - 如何将 http 标头传递给 VLC 播放器 Intent?
- mysql - 在 mySQL 中按日期排序不能使用简单的查询?
- python - 提取熊猫中特定列名的值,如另一列中列出的那样
- r - 检查多个子字符串的文本
- android - getActiveNotifications 返回 null
- javascript - 如何在接收服务器响应时动态创建标签?
- java - 将数组列表内容添加到提供空文本的文本视图