苹果推荐使用场景:
如果你编写的程序不是基于 UI 框架的,比如说命令行工具;
如果你编写的循环中创建了大量的临时对象;(常用)
如果你创建了一个辅助线程。
@interface ViewController () @property(strong, nonatomic) NSMutableArray *memoryUsageList; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //Init _memoryUsageList1 = [NSMutableArray new]; //创建一个串行队列 dispatch_queue_t serialQueue = dispatch_queue_create("test.autoreleasepool", DISPATCH_QUEUE_SERIAL); __block NSString *strTest; dispatch_sync(serialQueue, ^{ for (int i = 0; i < kIterationCount; i++) { @autoreleasepool { NSNumber *num = [NSNumber numberWithInt:i]; // 1 NSString *str = [NSString stringWithFormat:@"%d ", i]; // 2 //Use num and str...whatever... strTest = [NSString stringWithFormat:@"%@%@", num, str]; // 3 if (i % kStep == 0) { [_memoryUsageList1 addObject:@(getMemoryUsage())]; // getM方法是获取内存的函数 NSLog(@"000----%f", getMemoryUsage()); } } } }); } // 4
double getMemoryUsage(void) { struct task_basic_info info; mach_msg_type_number_t size = sizeof(info); kern_return_t kerr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size); double memoryUsageInMB = kerr == KERN_SUCCESS ? (info.resident_size / 1024.0 / 1024.0) : 0.0; return memoryUsageInMB; }
1,2行每次循环结束,会被系统自动释放。 主要看3行,释放时机应该是viewDidLoad函数结束释放,也就是第4行结束,strTest指向的堆内存空间也会释放。
每次for循环[NSString stringWithFormat:@"%@%@", num, str]都会在堆区开辟一份新的内存空间,strTest重新指向这个空间。之前不加释放池,以为这块内存空间在循环一次后会被自动释放,其实是系统在每一次runloop的同时自动加上释放池,在系统一次runloop结束的时候给池中对象发送release消息释放对象。这里手动添加池子的意义在于,每次for循环结束的时候,自动释放池都会释放[NSString stringWithFormat:@"%@%@", num, str]创建的内存空间,相当于@autoreleasepool给堆中内存添加了一个作用域,主要用于防止瞬时内存过大导致的闪退。也就是以上第二点的常用场景。