我不确定这是否是最好的设计设置,但我现在有这样的东西:
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
}
}
通过此设置,MyView 和 NextView 不会在 UIViewController 从根 UIViewController 更改后取消初始化。如果我将 var nextView 更改为弱 var nextView,则会调用取消初始化项,但在类加载后立即将 nextView 变为零。函数 go() 不会被调用。
如何在 MyView 所在的 UIViewController 取消初始化时取消初始化这两个类?
您的NextView
没有被取消初始化的原因是,在此设置中,MyView
持有对NextView
的强引用(并且只有一个)。如果将其设置为weak
引用,则任何强引用都不会保留NextView
,并立即取消初始化。
内存在经典 UI 层次结构中的工作方式如下 - 视图包含对其每个子视图的强引用,而对其超级视图的弱引用。这可以防止保留周期,同时允许删除视图以"级联"其所有子视图的取消初始化。
默认情况下,使用addSubview
方法会自动创建此强引用,如文档中所述。
此方法建立对视图的强引用,并将其下一个响应者设置为接收器,即其新的超级视图。
因此,在您的情况下,这样做的好方法可能是使用以下代码更新您的代码MyView
override func layoutSubviews() {
super.layoutSubviews()
nextView = NextView()
addSubview(nextView)
nextView!.go()
}
希望对您有所帮助!
我不想过多地评论代码本身,因为这不是主题,但我很确定在 layoutSubviews 中创建子视图是一个糟糕的主意。
同样在您的情况下,您每次都会重新创建此视图,这可能会产生计算开销。如果您只想创建一次,请使用
override func layoutSubviews() {
super.layoutSubviews()
if nextView == nil {
nextView = NextView()
addSubview(nextView)
nextView!.go()
}
}