@autoreleasepool-内存的分配与释放 开发过iOS、Mac的朋友应该对“ @autoreleasepool ”不陌生。只要在Xcode里建立一个工程,就能看到下面这样的代码: //iOS program int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } //Command line program int main(int argc, const char *argv[]) { @autoreleasepool { //... } return 0; } 看,每一个 main 函数的主体都被 @autoreleasepool 的Block块包在里面,也就是说,接下来全部的对象建立都在这个block里面。 那么, @autoreleasepool 的做用究竟是什么呢?咱们开发中能够用它来作什么呢? 能够在某些状况下,大幅度下降程序的内存占用,以下图: 测试的内容:500000次循环,每次循环建立一个NSNumber实例和两个NSString实例。 图:红线表示没有用 @autoreleasepool 时的内存占用。 图:绿线表示用了 @autoreleasepool 优化后的内存占用! 效果是否是很明显! 代码Github地址: AutoReleasePoolTestExample Xcode 6, iOS 8, iPhone 5模拟器. MRC 与 ARC MRC(Mannul Reference Counting)和ARC(Automatic Reference Counting),分别对应着手动引用计数和自动引用计数。 对!是计数,不是“ GC、垃圾回收 ”什么的,就是说,在Objective-C的开发中,ARC不表明像Java那样有GC作垃圾回收,因此本质上仍是要“手动”管理内存的。也就是说,咱们在ARC环境下写的代码,不用本身手动插入“ retain、release这些消息 ”,ARC会在编译时为咱们在合适的位置插入,释放没必要要的内存。 而 @autoreleasepool 就跟对象的 release 密切相关。 @autoreleasepool 干了啥 在MRC时代,若是咱们想先retain一个对象,可是并不知道在何时能够release它,咱们能够像下面这么作: NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString* str = [[[NSString alloc] initWithString:@"tutuge"] autorelease]; //use str... [pool release]; //str is released 就是说,咱们能够在建立对象的时候给对象发送“ autorelease ”消息,而后当 NSAutoreleasePool 结束的时候,“标记过”autorelease的对象都会被“ release ”掉,也就是会被释放掉。 可是在ARC时代,咱们不用手动发送 autorelease 消息,ARC会自动帮咱们加。而这个时候, @autoreleasepool 作的事情,跟 NSAutoreleasePool 就如出一辙了。 何时用@autoreleasepool 根据 Apple的文档 ,使用场景以下: 写基于命令行的的程序时,就是没有UI框架,如AppKit等Cocoa框架时。 写循环,循环里面包含了大量临时建立的对象。(本文的例子) 建立了新的线程。(非Cocoa程序建立线程时才须要) 长时间在后台运行的任务。 利用@autoreleasepool优化循环 利用@autoreleasepool优化循环的内存占用,我以为最有用的一点,下面就说说这个点。 以下面的循环,次数很是多,并且循环体里面的对象都是临时建立使用的,就能够用 @autoreleasepool 包起来,让每次循环结束时,能够及时的释放临时对象的内存。 //来自Apple文档,见参考 NSArray *urls = <# An array of file URLs #>; for (NSURL *url in urls) { @autoreleasepool { NSError *error; NSString *fileContents = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error]; /* Process the string, creating and autoreleasing more objects. */ } } 这么作的效果是极其显著地,就如本文最开始的图同样,能够本身把示例工程下回来运行下试试~ 总结 @autoreleasepool看起来很不“起眼”,日常开发很容易就忽略它了,可是仔细一看,确如此有用~ 参考