52
    UIView.animateWithDuration(1,
        animations: { [unowned self] in
            self.box.center = self.boxTopRightPosition
        },
        completion: { [unowned self] completed in
            self.box.hidden = true
    })

是否有必要避免内存泄漏?

4

6 回答 6

64

不,在这种情况下不需要。animations并且completion不保留,self因此不存在强保留周期的风险。

于 2014-11-19T14:53:04.043 回答
51

好吧,“必要”与“推荐”不同。如果您的问题是是否有必要,那么@Kirsteins 的回答很好,但是想象一下您想在某些工作后在视图控制器中为某些内容设置动画但您的视图控制器已被释放的情况(因为它不再在视图层次结构中或任何其他原因)。在这种情况下,如果您不使用[weak self],您的视图控制器在完成动画之前不会被释放,因为您将它保留在动画块中,但是保留它直到为不在动画块中的东西设置动画是否有意义再看?

因此,简而言之,在为 UIKit 制作动画时,您不需要使用weak对 self 的引用,但是,如果它被释放,您不需要保留视图,因为没有视图的动画没有意义,所以使用weak是一个不错的选择。

于 2016-08-31T13:37:47.563 回答
37

不,它不需要。正如柯斯坦斯所说:

不,在这种情况下不需要。动画和完成不会被 self 保留,因此不存在强保留周期的风险。

但是lhmgrassi说:

一旦它被释放,将调用 deinitializer 并且永远不会执行完成。

我不认为这是真的。将始终调用完成块。而且,如果您使用强自我,则在执行完成块之前,您的对象不会被释放。

但是,如果您使用 a [weak self],则您的对象不会(临时)由完成块保留,并且可能在触发完成块之前被释放。完成块仍然被触发,但self已经是nil.

如果您[unowned self]在完成处理程序中使用 a,您的对象也可能在完成处理程序被调用之前被释放,这可能导致崩溃!

我做了一个例子来说明这一点。

[gif 说明问题

完整的源代码可以在 Github上找到

于 2018-12-02T20:23:45.067 回答
6

@Plabo,正如@Kirsteins 所说,动画和完成不会由自己保留,因此即使您启动动画并且出于任何原因您的视图控制器已被释放,它也会立即释放。因此,您不需要捕获的“自我”。考虑下面这个愚蠢的例子:

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

}

一旦它被释放,将调用 deinitializer 并且永远不会执行完成。

于 2017-06-23T12:02:49.813 回答
5

恰好相反。您希望 self继续存在足够长的时间以调用完成块。因此,self通过转义完成处理程序变得强大并保留是一件好事

通常导致人们使用的担心weak self是保留循环。但这不是那个。一个保留循环是当self保留一个保留的闭包时self,导致泄漏,因为现在self永远不能被释放。但这根本不是那种情况。关闭,因此self,被保留,但不是self!所以暂时会有一些保留,但这是好的,还不错。

于 2018-12-02T20:35:16.680 回答
1

不需要在动画、GCD 或完成处理程序中使用弱/无主,因为:

他们捕获的外部对象引用只会保留 固定时间,这意味着它肯定会在某个时间点执行。在此之后,它将被释放,因此没有可能导致内存泄漏的引用循环。

正如之前的答案所暗示的,

如果动画完成不是自己保留的,那么谁保留它们?

我没有找到任何文件证据,但我相信它们是由 self 自己保留的,但时间固定。在此之后,完成执行并释放 self,从而导致 self 的解除分配。

在retain cycle场景中,闭包被self和self被闭包无限期地保留,这被认为是引用循环和内存泄漏。

于 2019-05-22T15:27:47.557 回答