我正在使用show segue和unwind segue在两个iOS
viewController VC1和VC2之间导航。在VC2的viewDidLoad()
中,我使VC2为观察者。这是我的代码:
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "buzzer updated"), object: nil, queue: OperationQueue.main) { _ in
print("set beeperViewImage")
}
}
每次我使用unsegue segue从VC2返回VC1时,addObserver()
被调用一个额外的时间,例如,在第四次返回segue
时addObserver被调用4次;在第五个segue
上进行五次,等等。即使将应用程序发送到后台并重新调用,也会发生这种情况。它会记住上一次会话发生了多少次segue,并从那里获取计数。
在最初的VC1中,我对多个调用没有问题。
我试图在取消锁定后将VC2设置为nil。
期待任何指导。
答案 0 :(得分:0)
这无疑是没有释放视图控制器的情况。也许您的参考周期很长。
例如,考虑这个无害的示例:
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次,然后单击“调试内存图”按钮,则会看到以下内容:
我可以在左侧面板中看到我的第二个视图控制器的三个实例,如果它们被正确地重新分配,它们将不会显示在那里。当我在该面板中单击任意一个时,我可以看到一个可视化图形,该图形仍然对所讨论的视图控制器具有很强的参考价值。
在这种情况下,由于我打开了“产品”»“方案”»“编辑方案...”»“运行”»“诊断”»“日志记录”下的“ Malloc堆栈”功能,因此可以看到堆栈跟踪显示在最右边的面板中,甚至可以单击箭头按钮,然后转到有问题的代码:
在此特定示例中,问题是我(故意地出于说明目的)引入了持久的强引用,其中通知中心保持了对self
的强引用,这是由观察者的关闭造成的。通过在该闭包中使用[weak self]
模式,可以轻松解决此问题:
NotificationCenter.default.addObserver(forName: .buzzer, object: nil, queue: .main) { [weak self] _ in
self?.foo()
}
现在,由于您的代码段中的代码实际上并未引用self
,因此我不知道这是否是强引用周期的源头。与我们共享代码段时,也许您简化了代码段。也许您还有其他东西完全在引用您的视图控制器。
但是通过使用“调试内存图”按钮,您不仅可以(a)确认内存中确实存在相关视图控制器的多个实例;而且(b)找出建立该强引用的依据。从那里,您可以诊断出问题的根本原因是什么。但是您问题中的代码不足以产生此问题,但是我怀疑某个地方有很强的参考周期。
答案 1 :(得分:0)
谢谢大家对我的问题的评论。基于这些内容,我开始搜索VC2可能保留的内容。原来,在我的VC2 viewWillAppear()中读取蓝牙无线链接的调用是罪魁祸首,但我不明白为什么:
self.radio?.peripheral?.readValue(for: (self.radio?.buzzerChar)!)
删除上面的代码行后,一切正常。再次感谢您指出搜索方向。