UIView.animateWithDuration(1, animations: { [unowned self] in self.box.center = self.boxTopRightPosition }, completion: { [unowned self] completed in self.box.hidden = true })
是否有必要避免内存泄漏?
8yparm6h1#
不,在这种情况下不需要。animations和completion不被self保留,因此不存在强保留周期的风险。
animations
completion
self
fcy6dtqo2#
当然,“必要”和“推荐”是不一样的。如果你的问题是“是否有必要”,那么@Kirsteins的回答很好,但是想象一下这样的情况:你想在完成一些工作后在视图控制器中制作动画,但是视图控制器已经被释放了(因为它不再处于视图层次结构中或任何其他原因).在这种情况下,如果不使用[weak self],视图控制器在动画完成之前不会被释放,因为您将其保留在动画块中,但在动画化视图中不再存在的内容之前保留它是否有意义?因此,简而言之,在制作UIKit动画时,您不 * 需要 * 使用weak引用self,但是,如果发布了视图,您不需要保留视图,因为没有视图的动画没有意义,因此使用weak是一个很好的选择。
[weak self]
weak
x4shl7ld3#
不需要。正如Kirsteins所说:不,在这种情况下不需要。动画和完成不是由自己保留的,所以没有强保留周期的风险。但是lhmgrassi说:一旦它被解除分配,解除初始化程序将被调用,完成将永远不会被执行。我不认为这是真的。完成块总是会被调用。如果你使用一个强self,你的对象在完成块被执行之前不会被释放。然而,如果你使用[weak self],你的对象不会(临时)被完成块保留,并且可能在完成块被激发之前被释放。完成块仍然被激发,但是self已经是nil。如果在完成处理程序中使用[unowned self],则对象也可能在调用完成处理程序之前被释放,这可能会导致崩溃!我举了一个例子来说明这一点。
nil
[unowned self]
完整的源代码可以在Github上找到
f2uvfpb94#
@Plabo,正如@Kirsteins所说,动画和补全并不是由self保留的,所以即使你启动了一个动画,而你的视图控制器由于某种原因被释放了,它也会立即被释放。所以,你不需要捕获“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") } }
一旦它被解除分配,解除初始化程序将被调用,完成将永远不会被执行。
siotufzp5#
正好相反,你 * 希望 * self继续存在足够长的时间,以便完成块被调用。因此,让self很强,并通过转义完成处理程序保留下来是一件 * 好事 *。通常人们使用weak self的担心是一个保留 * 循环 *。但这不是。保留循环是当self保留闭包时,闭包保留self,导致泄漏,因为self永远不能被释放。但这根本不是那种情况。闭包,因此self,被保留了。但不是由self!所以有一些保留正在进行,暂时的,但它是 * 好 *,不坏。
weak self
bq3bfh9z6#
不需要在动画、GCD或完成处理程序中使用弱/无主,因为:它们捕获的外部对象引用将只保留固定时间***,这意味着它将在一个时间点被确定执行。在此之后,它将被释放,因此不存在导致内存泄漏的引用循环的机会。如前面的答复所示,如果动画和完成不是自己保留的,那么谁保留它们?我没有找到任何书面证据,但我相信它们被自我保留了一段固定的时间***。在这之后,完成执行并释放自我,这导致了自我的解除分配。在保留循环场景中,闭包被self和self被闭包保留不确定的时间,这被认为是引用循环和内存泄漏。
mccptt677#
在这个问题上有许多错误的答案。weak self从来不需要动画。一旦你在ViewController上调用dismiss,动画完成将被调用(成功为false),并且你的ViewController将被释放,即使有一个强自引用。使用此测试:
dismiss
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") } }
在日志中,您将获得:
finished: false deinit
6秒后
7条答案
按热度按时间8yparm6h1#
不,在这种情况下不需要。
animations
和completion
不被self
保留,因此不存在强保留周期的风险。fcy6dtqo2#
当然,“必要”和“推荐”是不一样的。如果你的问题是“是否有必要”,那么@Kirsteins的回答很好,但是想象一下这样的情况:你想在完成一些工作后在视图控制器中制作动画,但是视图控制器已经被释放了(因为它不再处于视图层次结构中或任何其他原因).在这种情况下,如果不使用
[weak self]
,视图控制器在动画完成之前不会被释放,因为您将其保留在动画块中,但在动画化视图中不再存在的内容之前保留它是否有意义?因此,简而言之,在制作UIKit动画时,您不 * 需要 * 使用
weak
引用self,但是,如果发布了视图,您不需要保留视图,因为没有视图的动画没有意义,因此使用weak
是一个很好的选择。x4shl7ld3#
不需要。正如Kirsteins所说:
不,在这种情况下不需要。动画和完成不是由自己保留的,所以没有强保留周期的风险。
但是lhmgrassi说:
一旦它被解除分配,解除初始化程序将被调用,完成将永远不会被执行。
我不认为这是真的。完成块总是会被调用。如果你使用一个强self,你的对象在完成块被执行之前不会被释放。
然而,如果你使用
[weak self]
,你的对象不会(临时)被完成块保留,并且可能在完成块被激发之前被释放。完成块仍然被激发,但是self
已经是nil
。如果在完成处理程序中使用
[unowned self]
,则对象也可能在调用完成处理程序之前被释放,这可能会导致崩溃!我举了一个例子来说明这一点。
完整的源代码可以在Github上找到
f2uvfpb94#
@Plabo,正如@Kirsteins所说,动画和补全并不是由self保留的,所以即使你启动了一个动画,而你的视图控制器由于某种原因被释放了,它也会立即被释放。所以,你不需要捕获“self”。考虑下面这个愚蠢的例子:
一旦它被解除分配,解除初始化程序将被调用,完成将永远不会被执行。
siotufzp5#
正好相反,你 * 希望 *
self
继续存在足够长的时间,以便完成块被调用。因此,让self
很强,并通过转义完成处理程序保留下来是一件 * 好事 *。通常人们使用
weak self
的担心是一个保留 * 循环 *。但这不是。保留循环是当self
保留闭包时,闭包保留self
,导致泄漏,因为self
永远不能被释放。但这根本不是那种情况。闭包,因此self
,被保留了。但不是由self
!所以有一些保留正在进行,暂时的,但它是 * 好 *,不坏。bq3bfh9z6#
不需要在动画、GCD或完成处理程序中使用弱/无主,因为:
它们捕获的外部对象引用将只保留固定时间***,这意味着它将在一个时间点被确定执行。在此之后,它将被释放,因此不存在导致内存泄漏的引用循环的机会。
如前面的答复所示,
如果动画和完成不是自己保留的,那么谁保留它们?
我没有找到任何书面证据,但我相信它们被自我保留了一段固定的时间***。在这之后,完成执行并释放自我,这导致了自我的解除分配。
在保留循环场景中,闭包被self和self被闭包保留不确定的时间,这被认为是引用循环和内存泄漏。
mccptt677#
在这个问题上有许多错误的答案。
weak self
从来不需要动画。一旦你在ViewController上调用
dismiss
,动画完成将被调用(成功为false),并且你的ViewController将被释放,即使有一个强自引用。使用此测试:
在日志中,您将获得:
6秒后