是否有必要在UIView.animateWithDuration(...)的闭包中使用[unowned self]?

时间:2014-11-19 14:45:10

标签: ios memory swift closures

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

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

6 个答案:

答案 0 :(得分:46)

不,在这种情况下不需要。 animations completionself不会保留{{1}},因此不存在强保留周期的风险。

答案 1 :(得分:22)

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

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

答案 2 :(得分:7)

否,不需要。正如Kirsteins所说:

  

否,在这种情况下不需要。动画和完成不是自己保留的,因此没有强大的保留周期的风险。

但是lhmgrassi说:

  

一旦解除分配,将调用反初始化器,并且将永远不会执行完成。

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

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

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

我已经举例说明了这一点。

[gif illustrating the issue

完整来源可以为found on Github

答案 3 :(得分:6)

@Plabo,正如@Kirsteins所说,动画和完成不会被自己保留,所以即使你开始动画并且出于任何原因你的视图控制器已被释放,它也会立即解除分配。所以,你不需要捕获'自我'。 考虑一下这个愚蠢的例子:

String s = getIntent().getStringExtra("USER_NAME");

一旦取消分配,将调用deinitializer并且永远不会执行完成。

答案 4 :(得分:2)

正好相反。您想要 self继续存在足够长的时间,以便调用完成块。因此,使self强大并通过转义的完成处理程序保留下来是一件事情。

通常使人们使用weak self的烦恼是保留周期。但这不是那样。保留周期是self保留保留self的闭包时,由于现在self再也无法释放而导致泄漏的原因。但这根本不是那种情况。闭包,因此self,将被保留,而不是self!因此,暂时会有一些保留,但这是,还不错。

答案 5 :(得分:0)

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

它们捕获的外部对象引用将仅保留用于 固定时间 ,这意味着它将在某个时间点执行。在此之后,它将被释放,因此不会出现导致内存泄漏的参考周期。

如先前的答案所示,

  

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

我没有发现任何书面证据,但是我相信 它们是由自己自己保留的,但是固定的时间是 。此后,完成执行并释放自我,从而导致自我的取消分配。

在保留周期方案中,闭包由self和self由闭包保留无限期,这被视为参考周期和内存泄漏。