关闭变量不能解除分配

时间:2014-10-22 01:00:12

标签: ios objective-c xcode memory-management swift

我描述问题的最简单方法是用一个小例子来展示。

//In a swift file

myObjectiveCObject.setCallbackBlock {(object: AnyObject!) -> Void in

    var chunkOfMemory = //fill up var with memory stuff. Self is never referenced.

}

myObjectiveCObject.startParsing()


//In the objective-c class file

@property (nonatomic, copy) MyBlockType callbackBlock;

- (void)startParsing {

    //loop around thousands of times calling
    self.callbackBlock(someNewObject)

}


在完成objective-c对象之前,每个闭包调用分配的内存都不会被释放。当然,预期的行为是在每次闭包调用后释放内存吗?

1 个答案:

答案 0 :(得分:1)

如果一个实例化自动释放对象,但不定期排出自动释放池,则会出现这种问题。通常,在您回退到运行循环(或操作或调度任务完成)之前,池不会被耗尽。因此,您总是必须非常小心地循环数千次。 (参见{em>使用本地自动释放池块来减少峰值内存占用部分{/ 3}}。)

通常通过创建(从而耗尽)您自己的本地自动释放池来控制此峰值内存使用量:

- (void)startParsing {

    // loop around thousands of times

    for ( ... ) {  
        @autoreleasepool {
            // do whatever

            self.callbackBlock(someNewObject)
        }
    }    
}

有一个等效的Swift函数,不出所料地称为autoreleasepool(),所以如果你知道自动释放对象是由你的闭包创建的东西创建的,你也可以在那里解决它。没有看到代码或在Instruments中分析代码,很难猜出哪个是创建自动释放对象。 (注意,是的,我知道原生的Swift对象通常不会被自动释放,但你无法保证Swift闭包调用的任何代码,这就是Swift提供autoreleasepool函数的原因。)< / p>

如果你真的想要诊断它,可以在Instruments中运行它,并在startParsing完成之前暂停它,并查看尚未发布的内容,并回溯到这些对象的位置实例化,这将有助于您诊断自动释放对象的创建位置,从而确认您需要添加池的位置。

显然,在处理大型循环时,除了自动释放对象(例如,同时在内存中保存太多大型资源(图像等))之外,还存在这些类型的内存问题的其他来源,递归调用函数等)。但我认为你已经检查过你的代码,看看那些明显的代码。所以自动释放对象是另一件需要检查的事情。