------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net
培训</a>、期待与您交流! -------
1、什么是内存管理
内存管理是oc中非常重要的一块内容。不了解内存管理的实质,不仅容易在编写程序的时候报错,而且也不利于成语运行的流畅性。因此处理好内存管理,是非常有必要的。
当下的移动设备的内存极其有限,像当下大部分手机内存为2G,而每个app所能占用的内存是有限制的,当app所占用的内存较多时,系统会发出内存警告,这时得回收一些不需要再使用的内存空间。比如回收一些不需要使用的对象、变量。
管理范围:任何继承了NSObject的对象,对其他基本数据类型(int、char、float、double、struct、enum等)无效。
2、引用计数器
每个OC对象都有自己的引用计数器,是一个整数,表示“对象被引用的次数”,即有多少人正在使用这个OC对象,每个OC对象内部专门有4个字节的存储空间来存储引用计数器。
3、引用计数器的作用
当使用alloc、new或者copy创建一个新对象时,新对象的引用计数器默认就是1。当一个对象的引用计数器值为0时,对象占用的内存就会被系统回收。换句话说,如果对象的计数器不为0,那么在整个程序运行过程,它占用的内存就不可能被回收,除非整个程序已经退出。
4、引用计数器的操作
给对象发送一条retain消息,可以使引用计数器值+1(retain方法返回对象本身);给对象发送一条release消息,可以使引用计数器值-1;可以给对象发送retainCount消息获得当前的引用计数器值。
引用计数器的不恰当操作,可能会产生僵尸对象与野指针。
僵尸对象:当应用计数器为0时,对象所占用的内存将会被销毁,对象即变成僵尸对象。
野指针:新建一个对象指针,当指针所指向的对象变成僵尸对象,那么该指针就变成了野指针。
空指针:指针内指向的地址值为0,即指针不指向任何对象。
定义一个Person对象,对其进行引用计数器操作。
Person *p = [[Person alloc]init]; // 此时引用计数器的值为1
[p retain]; //引用计数器的值为2
[p release]; //引用计数器的值为1
[p release]; //引用计数器的值为0,此时p指向一个僵尸对象
[p release]; // p指向一个僵尸对象,程序报错。
p = nil; //p设为空指针
5、对象的销毁
当一个对象的引用计数器值为0时,那么它将被销毁,其占用的内存被系统回收;当一个对象被销毁时,系统会自动向对象发送一条dealloc消息;一般会重写dealloc方法,在这里释放相关资源,dealloc就像对象的遗言;一旦重写了dealloc方法,就必须调用[super dealloc],并且放在最后面调用。不要直接调用dealloc方法,一旦对象被回收了,它占用的内存就不再可用,坚持使用会导致程序崩溃(野指针错误)。
重写dealloc方法:
- (void)dealloc; //声明
- (void)dealloc //实现
{
NSLog(@“销毁一个对象”);
[super dealloc];
}
[super dealloc]写在dealloc重写的最后面调用,是因为子类重写完dealloc后,父类中的dealloc必须单独调用。
5、多对象内存管理
如果你通过alloc、new或[mutable]copy来创建一个对象,那么你必须调用release或autorelease换句话说,不是你创建的,就不用你去release。多对象管理坚持一个原则,就是谁retain,谁release,只要你调用了retain,无论这个对象是如何生成的,你都要调用release。有始有终,有加就有减,曾经让对象的计数器+1,就必须在最后让对象计数器-1,这样就能报错引用计数器的平衡,保证不会乱套与出错。
set方法内存管理代码规范:
以对象Person为例:
if(person != _person) //判断是否是新对象,如果是新的才进行操作
{
[_person release]; //对当前对象也就是之前就有的对象进行release操作
_person = [person retain]; // 对传入的新对象进行retain操作,并赋值给当前对象
}