UIView.animateWithDuration(1,
animations: { [unowned self] in
self.box.center = self.boxTopRightPosition
},
completion: { [unowned self] completed in
self.box.hidden = true
})
需要避免内存泄漏吗?
UIView.animateWithDuration(1,
animations: { [unowned self] in
self.box.center = self.boxTopRightPosition
},
completion: { [unowned self] completed in
self.box.hidden = true
})
需要避免内存泄漏吗?
不需要在这种情况下使用。 animations
和completion
都没有被self
保留,因此不存在强引用循环的风险。
@noescape
功能。 - Kirsteins好的,“必要”并不等同于“推荐”。如果您的问题是是否必要,那么@Kirsteins的回答就足够了,但请想象一下这样一种情况:在完成某些工作后,您希望在视图控制器中动画显示某些内容,但您的视图控制器已被释放(因为它不再位于视图层次结构中或任何其他原因)。在这种情况下,如果您不使用[weak self]
,则您的视图控制器将在完成动画之前无法释放,因为您在动画块中保留了它,但将其保留到动画一个不再显示的视图中是否有意义呢?
因此,简而言之,在使用UIKit动画时,您需要使用一个weak
引用来引用自身,但是,如果视图被释放,则无需保留视图,因为没有视图的动画是没有意义的,因此使用weak
是一个好选择。
[weak self]
或[unowned self]
只是为了控制流程,而不是解决内存问题。最终它们会执行/完成并释放对象(取决于块所需的时间,可以是2秒、10秒或200秒)。更多相关信息,请参见如何使用dispatchQueues创建引用循环?。 - mfaani不需要。如Kirsteins所说:
不,在这种情况下不需要。动画和完成不会被self保留,因此不存在强引用循环的风险。
但是lhmgrassi说:
只要它释放了,析构函数就会被调用,完成块将永远不会被执行。
我认为这并不正确。完成块总是会被调用。如果使用了强self,您的对象在完成块执行之前不会被释放。
然而,如果使用了[weak self]
,则您的对象不会被完成块(暂时)保留,可能会在完成块被触发之前被释放。完成块仍将被触发,但 self
已经是 nil
。
如果在完成处理程序中使用[unowned self]
,则您的对象也可能在完成处理程序被调用之前被释放,这可能会导致崩溃!
我制作了一个示例来说明这一点。
完整的源代码可以在 Github上找到
[weak self]
。 - CyberMewweak self
,它是一个全局函数,不会保留 self
。 - José@Plabo,正如@Kirsteins所说,动画和完成不被自身保留,因此即使您启动动画并且由于任何原因您的视图控制器已被释放,它也将立即被销毁。所以,您不需要捕获“self”。 考虑下面的愚蠢示例:
class ViewController: UIViewController {
@IBOutlet weak var button : UIButton!
override func viewDidLoad() {
super.viewDidLoad()
print("viewDidLoad ViewController")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
UIView.animate(withDuration: 20, animations: {
self.button.frame = CGRect(x: 0, y: 300, width: 30, height: 30)
}) { finished in
self.button.frame = CGRect(x: 0, y: 100, width: 30, height: 30)
}
}
deinit {
print("deinit ViewController")
}
}
self
继续存在足够长的时间,以便调用完成块。因此,通过逃逸完成处理程序强制保留self
是一件好事。weak self
的担忧是保留回路。但这不是那样的情况。保留回路是指self
保留了闭包,闭包又保留了self
,导致泄漏,因为现在self
永远不能释放。但这根本不是那种情况。闭包,因此self
被保留,但不是由self
保留!因此,仍然有一些保留正在进行,但这是一个好事,而不是坏事。我没有找到任何文件证据,但我相信它们由self自身保留,但只保留有限的时间。此后,完成处理程序执行并释放self,从而导致self的解除分配。如果动画和完成处理程序没有被self保留,那么谁会保留它们?
这个主题上有很多错误的答案。对于动画,weak self
是不需要的。
一旦在你的 ViewController 上调用 dismiss
,动画完成时将会被调用(成功为 false),即使有一个强引用的 self,你的 ViewController 也将被释放。
使用以下测试:
class TestVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .blue
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.view.alpha = 1
UIView.animate({
self.view.alpha = 0
}, duration: 40) { success in
print("finished: \(success)")
self.view.backgroundColor = .green
}
}
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
self.dismiss(animated: true)
}
}
deinit {
print("deinit")
}
}
(请注意40秒的动画持续时间) 在6秒后,您将获得以下日志:
finished: false
deinit