关于@autoreleasepool

苹果推荐使用场景: 

   如果你编写的程序不是基于 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给堆中内存添加了一个作用域,主要用于防止瞬时内存过大导致的闪退。也就是以上第二点的常用场景。

摘自

原文地址:https://www.cnblogs.com/jztsdwn/p/8758441.html