带有定时器的类的UIView可以防止初始化



我不确定这是否是最好的设计设置,但我现在有这样的东西:

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()
}
}

最新更新