引起强参考周期的通知中心 - Swift 5



在使用通知中心时,我似乎得到了一个强大的参考周期。

我正在使用通知中心来观察设备的旋转。(虽然有些人会认为这不是确定设备旋转的最佳方法,但这目前似乎是我唯一的途径,因为没有使用自动布局,也没有使用情节提要(。

deinit {}

永远不会在我的ViewController中被调用,即使我在viewWillDisappearviewDidDisappear中删除了观察者。

import UIKit
class TestVC: UIViewController {

deinit {
print("TestClass Deinit") //not being triggered ever
}
@objc private func rotationDetected(sender: Any) {
print("we rotated")
}
override func viewDidDisappear(_ animated: Bool) {
//NotificationCenter.default.removeObserver(UIDevice.orientationDidChangeNotification)
}
override func viewWillDisappear(_ animated: Bool) {
NotificationCenter.default.removeObserver(UIDevice.orientationDidChangeNotification)
//NotificationCenter.default.removeObserver(self) //also doesn't work
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
NotificationCenter.default.addObserver(forName: UIDevice.orientationDidChangeNotification, object: nil, queue: .main, using: rotationDetected)
}
override func viewDidLoad() {
super.viewDidLoad()
}

}

关于为什么会发生这种情况以及如何解决它的任何想法?

也对有关如何确定旋转检测的其他方式的任何新想法持开放态度(尽管没有使用自动布局或情节提要(。

为了达到TestVC()我在前ViewController中使用了self.navigationController?.pushViewController(TestVC(), animated: true),为了返回,我使用pop

如果没有Observer,类将正确deinit

解决

由于下面标记的答案,强参考周期被删除。

只需更换NotificationCenter.default.addObserver(forName: UIDevice.orientationDidChangeNotification, object: nil, queue: .main, using: rotationDetected)

NotificationCenter.default.addObserver(self, selector: #selector(rotationDetected), name: UIDevice.orientationDidChangeNotification, object: nil)

这应该适用于viewWillDisappear

NotificationCenter.default.removeObserver(self, name: UIDevice.orientationDidChangeNotification, object: nil)

结合在viewWillAppear中使用以下方法:

NotificationCenter.default.addObserver(self, selector: #selector(rotationDetected), name: UIDevice.orientationDidChangeNotification, object: nil)

您删除观察器的方法不正确,您应该这样做:

class TestVC {
private var observer: Any
func viewWillAppear() {
observer = NotificationCenter.default.addObserver(forName: UIDevice.orientationDidChangeNotification, object: nil, queue: .main, using: rotationDetected)
}
func viewWillDisappear() {
NotificationCenter.default.removeObserver(observer)
}
}

要消除强参考周期,请在闭包中使用弱参考循环。

最新更新