在 iOS 中,某些视图控制器在关闭后不会被释放。
经过网上研究,我发现委托应该设置为
weak
,并且在闭包中,您应该在访问 self 变量之前使用[weak self]
。
应用该解决方案后,我的视图控制器在被关闭后现在可以正确释放。
我有一个问题:动画块中需要使用【weak self】吗?
我在下面添加了两段代码;我该用哪一个?
// Without [weak self]
UIView.animate(withDuration: 0.25) {
self.loaderView.alpha = 0
} completion: { isFinish in
self.loaderView.isHidden = true
}
// With [weak self]
UIView.animate(withDuration: 0.25) {[weak self] in
guard let self = self else { return }
self.loaderView.alpha = 0
} completion: { [weak self] isFinish in
guard let self = self else { return }
self.loaderView.isHidden = true
}
我需要在动画块中使用[weak self]吗?
不,您不必“必须”使用
self
作为weak
参考,这取决于您的具体应用场景和您的要求。
所以你应该问自己的问题是: 我是否希望或需要能够在动画结束/取消之前释放
self
?
如果您的实际问题是您的代码是否触发强引用循环,那么答案是“否”。
经过网上研究,我发现委托应该设置为“弱”,并且在闭包中,在访问 self 变量之前应该使用 [weak self]。
弱引用与委托一起使用的原因之一是打破强引用循环。但仅仅因为您使用委托模式,并不意味着您必须使用弱引用。
我应该使用哪一个?
首先,请注意您的第二个变体可以以更紧凑的方式编写:
UIView.animate(withDuration: 0.25) { [weak self] in
self?.loaderView.alpha = 0
} completion: { [weak self] isFinish in
self?.loaderView.isHidden = true
}
一般来说,
UIView.animate
只有少数场景才需要使用弱引用。
当视图控制器被关闭时,其视图的所有正在运行的动画也会被取消,并立即调用完成处理程序。
这意味着动画只会稍微阻止视图控制器实例的释放。
为了说明这一点,我将向您展示一个人工场景,在该场景中您应该更仔细地考虑动画中止时的行为以及弱引用的使用:
final class MyViewController: UIViewController {
func loadData() {
UIView.animate(withDuration: 0.25) {
self.loaderView.alpha = 0
} completion: { finished in
self.hideLoadingView()
}
}
func hideLoadingView() {
DispatchQueue.global().async {
Thread.sleep(forTimeInterval: 5)
DispatchQueue.main.sync {
self.loaderView.isHidden = true
}
}
}
}
如果用户在调用
loadData
之后在这种情况下关闭视图控制器,则视图控制器实例将保持活动状态至少 5 秒。
如果使用弱引用,情况就不会如此。调度队列中的闭包仍会被调用,但它们将不再执行任何操作。
但是,再次强调,这只是为了更详细地解释问题而虚构的场景。当然,实际上,您永远不应该在
UIView.animate
处理程序中执行长时间运行的任务。