Autorelease pools 自动释放池

读完前面的章节,相信你已经对自动释放(autorelease)这个概念有自己的理解了,是时候来讲一讲自动释放池(autorelease pool)了。在引入 ARC 技术之前,自动释放池就已经被广泛使用了,实际上它是区别于 ARC 的一整套完整的技术。

新建了一个弱引用对象之后,它会被 ARC 是在「某个时刻」释放掉,这里的「某个时刻」经常是当前某个循环的结束的时候,再确切说就是「目前所有代码都执行完毕,接下来执行的是另一块代码」的时候。

这么做也不是十全十美。比如说你创建了一个对象,它占用了很多内存,而你不能在用完它的时候就立刻释放它,而要等整个代码都运行完了才能释放。

比如这个例子:

for (NSInteger i = 0; i < 100; ++i) {
    ComplexObject *obj = [ComplexObject new];
    [obj doLotsOfWork];
}

ComplexObject 和 doLotsOfWork 具体是什么这个细节无关紧要,你只要知道它们会占用很多内存就好了。

我们无法确切这些对象什么时候会销毁,ARC 可能会在整一个循环运行结束之后释放,也可能在这个循环的某一个位置自动释放,这是一个实现的细节,我们无法控制它。

然而当你使用 autorelease 的时候,要实打实先循环 100 次再释放对方。这就意味着光这个循环就要占有很大一部分内存,而这些占用内存的对象,它们只是等着被释放而已。

解决方法就是使用 @autoreleasepool 代码块。在此之前我们已经在 main.m 文件里和它打过招呼了,其实你可以在你想要的任意位置去创建它。当这个代码块运行完毕的时候,里面的所有对象都会被释放。

我们就可以把上面的代码写成这样:

for (NSInteger i = 0; i < 100; ++i) {
    @autoreleasepool {
        ComplexObject *obj = [ComplexObject new];
        [obj doLotsOfWork];
    }
}

在这种情况下,它就会自动的释放内存。举个例子就是,它就像一个池子,里面的水位代表了占用内存的多少。随着程序的运行,这个池子水位不停升高,但是由于我们在每一次使用完之后,都会把水放掉,这个水位就会一直保持在比较低的水平。

Objective-C 有一些方法是自带自动释放池的,比如 NSArray 的 enumerateObjectsUsingBlock,NSString 的 enumerateSubstringsInRange,它们的方法内部都是包含了自动释放池功能哒。

results matching ""

    No results matching ""