Ios 何时在解除视图控制器时自动解除分配

Ios 何时在解除视图控制器时自动解除分配,ios,objective-c,swift,automatic-ref-counting,objective-c-blocks,Ios,Objective C,Swift,Automatic Ref Counting,Objective C Blocks,我有一个关于内存释放和块/闭包的问题 以下是Swift方法 self!.dismissViewControllerAnimated(false, completion: { println(self); }) 还是客观的C方法 [self dismissViewControllerAnimated:NO completion:^{ NSLog("%@",self); }]; 如果有人能解释一下,在上述方法中,self何时会被解除分配

我有一个关于内存释放和块/闭包的问题

以下是Swift方法

    self!.dismissViewControllerAnimated(false, completion: {
        println(self);
     })
还是客观的C方法

   [self dismissViewControllerAnimated:NO completion:^{
       NSLog("%@",self);
   }];

如果有人能解释一下,在上述方法中,self何时会被解除分配,我将不胜感激。是在完成区块运行之后还是之前?我知道ARC已经注意到了这一点,但我想知道self是在完成块中还是之后收到了释放消息。因此,如果我在完成块(访问self)中进行一些小的清理,那么这是否安全/可接受?

要完全理解答案,实际上有两个独立的问题:

1.闭包内部引用的变量何时发布? 您可以将闭包看作是另一种类型(在Swift中,它们实际上是)。每个闭包都会对其中引用的变量产生强大的所有权,包括
self
。这可确保您永远不会引用已解除分配的变量。就像在任何其他对象中一样,当闭包被解除分配时,它将释放对其所有变量的所有权

如果闭包是唯一一个对该变量有强引用的对象,那么当闭包被解除分配时,该变量将被解除分配

简言之,只要闭包还在内存中,变量就会留在内存中

2.什么时候解除关闭? 现在,第二个需要理解的部分是,什么时候可以解除闭包。您可以将闭包存储在变量中:

func myMethod() {
    var myClosure = {
        println(self)
    }
    myClosure()
}
在这种情况下,闭包有一个来自其变量
myClosure
的强引用,并且闭包有一个来自
self
的强引用。一旦
myClosure
超出范围,即当
myMethod
退出时,它将被解除分配。当这种情况发生时,自我将被释放

您也可能遇到这样的情况,比如在您的问题中,您正在将闭包传递给另一个方法。在本例中,将闭包传递到的方法捕获对闭包的强引用。当该方法退出时,它将释放您的闭包,该闭包将被释放,并且它将释放其中捕获的所有变量

例外
有时有必要定义一个拥有变量所有权的闭包。这样做是为了避免循环引用。你可以在苹果的文档中阅读更多关于什么是循环引用以及如何防止循环引用的内容。但是,重要的是要认识到,除非您投入显式的努力(和代码),否则闭包将始终捕获对其中引用的变量的强引用。

在Swift中,在开发/调试和尝试理解操作时间时,您可以将以下内容添加到视图控制器(或任何类)中,跟踪实例是否或何时将要解除分配

尽管这无助于检测此处描述的“强参考周期”:


这肯定是在解雇完成之后。虽然不一定紧随其后。如果您在该闭包内引用了
self
,则闭包将保留对视图控制器的引用。将清理放在那里的行为应该保证视图控制器在闭包执行后才被释放。请看,这是一个很好的闭包捕获阅读。循环引用也称为“强引用循环”闭包有一个来自其变量myClosure的强引用什么?你是说myMethod,使用
var myClosure
定义了一个闭包,然后使用
myClosure()
运行闭包,该闭包强烈引用了
self
,一旦
myMethod
被解除,它将被解除?好的,但是你为什么不在这里再次使用
[弱自我]
deinit {
    println(__FUNCTION__, "\(self)")
}