NotifcationCenter 导致强引用循环 - Swift 5
NotifcationCenter causing a strong reference cycle - Swift 5
我似乎在使用 NotifcationCenter 时遇到了强引用循环。
我正在使用 NotificationCenter 观察设备的旋转。 (虽然有些人认为这不是确定设备旋转的最佳方法,但目前这似乎是我唯一的方法,因为没有使用自动布局,也没有使用情节提要)。
deinit {}
永远不会在我的 ViewController
中被调用,即使我在 viewWillDisappear
和 viewDidDisappear
.
中删除了观察者
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
不存在,class 将正确 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)
}
}
要消除强引用循环,请在闭包中使用 weak。
我似乎在使用 NotifcationCenter 时遇到了强引用循环。
我正在使用 NotificationCenter 观察设备的旋转。 (虽然有些人认为这不是确定设备旋转的最佳方法,但目前这似乎是我唯一的方法,因为没有使用自动布局,也没有使用情节提要)。
deinit {}
永远不会在我的 ViewController
中被调用,即使我在 viewWillDisappear
和 viewDidDisappear
.
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
不存在,class 将正确 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)
}
}
要消除强引用循环,请在闭包中使用 weak。