自动释放池是iOS中的内存回收机制,能够延迟对象的释放。当池中的对象超出作用域后并不会立即被释放,等待自动释放池销毁后,自动释放池会像池中的所有对象发送release消息(如果你给一个对象多次发送autorelease消息,那么当自动释放池销毁时,这个对象也会收到同样数目的release消息),释放池中的对象。
加入自动释放池
- MRC
NSObject *obj = [[NSObject alloc]init];
//需调用autorelease方法加入自动释放池
[obj autorelease];
//手动释放
[obj release];
- ARC
dog对象加入到block自动释放池,在出大括号后自动释放池销毁,向池中对象发送release消息,销毁了dog对象。
@autoreleasepool {
Dog *dog = [[Dog alloc]init];
NSLog(@"分割线----------------");
}
NSLog(@"自动释放池销毁");
//执行结果
分割线----------------
dog 销毁了
自动释放池已销毁
自动释放池的释放
对于手动创建的局部释放池在大括号结束后就会被释放(如上dog所在的是释放池),而每一次消息循环开始会创建一个全局释放池,而RunLoop释放池会等一次消息循环结束的时候释放。可以理解为在程序持续执行的时候不会销毁释放池,直到产生屏幕旋转,等待用户输入等事件,消息循环结束,销毁释放池,重新开始循环,创建全局释放池。
如下创建的str很多,而系统的类方法stringWithFormat:本质上是调用了alloc + initWithFormat: + autorelease,新建的str对象并不会立即释放,必须等到消息循环结束,造成内存飚升。
for (int i = 0; i < 10000000; i++) {
//系统类方法,会将创建的对象加入系统自动释放池
NSString *str = [NSString stringWithFormat:@"hello -%d", i];
//系统对象方法不会将创建的对象加入系统自动释放池,因此每次循环对象都会释放。
//NSString *str =[[NSString alloc]initWithFormat:@"hello -%d",i];
str = [str stringByAppendingString:@" - world"];
};
在循环内加入自动释放池,即可控制对象的释放。
for (int i = 0; i < 10000000; i++) {
@autoreleasepool {
NSString *str = [NSString stringWithFormat:@"hello -%d", i];
str = [str stringByAppendingString:@" - world"];
}
};
自动释放池应用场景
- 如果你编写的程序不是基于 UI 框架的,比如说命令行工具(不会自动创建外层的全局自动释放池);
- 如果你编写的循环中创建了大量的临时对象,如上;
- 如果你创建了一个辅助线程,主线程会自动创建外层的自动释放池。
PS: I am xinghun who is on the road.
网友评论