---------------------- IOS开发、Android培训、期待与您交流! ----------------------
一、autorelease
autorelease与release相似,是OC中的一个对象方法。这两个方法都能把对象的引用计数器减1,但是release是一个精确的减1,对对象的操作只能在release之前进行,如果是在之后,就会出现野指针错误;而autorelease是一个不精确的引用计数器减1,当给对象发送autorelease消息时,对象就会被放到自动释放池中,自动销毁时会给池中的所有对象发送release消息,使得所有对象的计数器减1,所以本质上autorelease还是会调用release。
二、自动释放池
上面小桥说了,autorelease对象方法会把对象放到自动释放池中,那么什么是自动释放池呢?如果读者看了第一篇笔记,就会知道小桥曾经把Xcode自动生成的代码做过删减,因为那时小桥还不知道那些代码的意思,删减的代码中就有自动释放池,小桥现在不删减main函数中的代码看看:
如图所示,所谓自动释放池就是由@autoreleasepool关键字声明的一个代码段,在其中用autorelease给对象发送消息就会把对象放个这个自动释放池中,当程序执行完自动释放池,释放池销毁,接着池中的每个对象都会收到一条release消息,使得各自的引用计数器减1。由于池中的对象只能在池过期时才能release,所以autorelease不能精确的回收一个对象,而是往往即使对象过期了,池中还有许多代码执行完,池过期了,全部对象才能release或回收。
三、autorelease的使用
小桥为了复习知识,依然要在这里用一用autorelease,所用到的全部代码为:
// // 文件:Person.h // 项目:博客笔记 // 作者:葬花 桥 // 日期:14-5-10 // 版权: Copyright (c) 2014年 itcast. All rights reserved. // #import <Foundation/Foundation.h> @interface Person : NSObject @property (nonatomic,retain) NSString *name; @property (nonatomic,assign) int age; @end
// // 文件:Person.m // 项目:博客笔记 // 作者:葬花 桥 // 日期:14-5-10 // 版权: Copyright (c) 2014年 itcast. All rights reserved. // #import "Person.h" @implementation Person - (void)dealloc { NSLog(@"%@--被回收了!", _name); [super dealloc]; } @end
// // main.m // autorelease与自动释放池 // // Created by 葬花 桥 on 14-5-10. // Copyright (c) 2014年 itcast. All rights reserved. // #import <Foundation/Foundation.h> #import "Person.h" int main(int argc, const char * argv[]) { @autoreleasepool // 自动释放池 { Person *p = [[[Person alloc] init] autorelease]; // 实例化Person类的对象 p.age = 10; // 调用setAge:方法 p.name = @"桥"; // 调用setName:方法 } // 自动释放池过期时给p指向的对象发送release消息 NSLog(@"main函数结束之前!"); return 0; }
如你看到的,小桥现在把创建对象和使用对象放在了@autorelease中,使用语句之后没有release,而是在创建对象的同时调用了autorelease方法,这同样也符合了内存管理原则1,谁alloc谁release或autorelease。使用了autorelease之后,我们不必再关心release要写在何处,我们只要保证,对对做操作在自动释放池中进行即可,在自动释放池销毁时,对象会自动收到release消息,而不必手动release。用下面的图附上佐证:
自动释放池可以嵌套使用,即在池中可以再生成一个池。
三、自动释放池的应用
自动释放池的应用还是比较多的,在上几篇的笔记中小桥没有提系统对象的内存管理,因为苹果官方已经写好了内存管理的代码封装在类中。比如NSString = @"小桥 ",字符串对象的内存管理封装在类内部,在外面就不用我们手动release。在这里小桥模拟一下它的封装过程,在Person声明部分声明一个类方法,方法名为
person(规范写法:类名但是第一个字母小字),这与C++的默认构造方法形式有一点相似但不同,在实现文件中实现这个方法
// // 文件:Person.m // 项目:博客笔记 // 作者:葬花 桥 // 日期:14-5-10 // 版权: Copyright (c) 2014年 itcast. All rights reserved. // #import "Person.h" @implementation Person - (void)dealloc { NSLog(@"%@--被回收了!", _name); [super dealloc]; } // 类方法的实现 + (id)person { Person *p = [[[Person alloc] init] autorelease]; // 创建一个对象,并调用autorelease方法加到自动释放池 return p; // 返回这个对象的地址 } @end
以后用高用这个类方法就可以创建Person类的对象,而且不必再手动release前提是要在自动释放池中去使用。NSString也是类似的,直接放到自动释放池中使用
下面这张图可以间接证明:
---------------------- IOS开发、Android培训、期待与您交流! ---------------------- 详细请查看:www.itheima.com
黑马程序员-OC学习笔记之autorelease与自动释放池