我不确定这是否是最好的设计设置,但我现在有这样的东西:
class MyView: UIView {
var nextView: NextView?
override func layoutSubviews() {
super.layoutSubviews()
nextView = NextView()
nextView!.go()
}
deinit {
print("call me")
}
}
class NextView {
var timer: Timer?
func go() {
timer = Timer.scheduledTimer(withTimeInterval: 1,
repeats: true,
block: { [weak self] _ in })
}
deinit {
print("call me")
timer?.invalidate()
timer = nil
}
}
通过此设置,在 UIViewController 从根 UIViewController 更改后,MyView 和 NextView 不会取消初始化。如果我将 var nextView 更改为弱 var nextView,则会调用反初始化器,但在类加载后 nextView 为零。函数 go() 不会被调用。
当 MyView 所在的 UIViewController 取消初始化并取消初始化时,如何取消初始化这两个类?
最佳答案
你的NextView
的原因没有被取消初始化是因为,在此设置中,MyView
拥有对 NextView
的强引用(且仅有一个) 。如果你把它设为weak
引用,然后NextView
不被任何强引用保留并立即取消初始化。
内存在经典 UI 层次结构中的工作方式如下 - View 对其每个 subview 拥有强引用,对其父 View 拥有弱引用。这可以防止保留循环,同时允许删除 View 以“级联”其所有 subview 的反初始化。
默认情况下,使用方法 addSubview
自动创建这个强引用,如 documentation 中所写。 .
This method establishes a strong reference to view and sets its next responder to the receiver, which is its new superview.
因此,在您的情况下,最好的方法可能是使用 MyView
中的以下内容更新您的代码
override func layoutSubviews() {
super.layoutSubviews()
nextView = NextView()
addSubview(nextView)
nextView!.go()
}
希望有帮助!
<小时/>我不想对代码本身发表太多评论,因为这不是主题,但我很确定在layoutSubviews 中创建 subview 是一个糟糕的主意。
此外,在您的情况下,您每次都将重新创建此 View ,这可能会导致计算成本高昂。如果您只想创建一次,请使用
override func layoutSubviews() {
super.layoutSubviews()
if nextView == nil {
nextView = NextView()
addSubview(nextView)
nextView!.go()
}
}
关于swift - 带有计时器类的 UIView 可以防止 deinit,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49698734/