内存管理是OC学习中最重要的环节,学而习之,习儿惯之。重点!!!
基本原理
1、什么是内存管理
(1) 移动设备的内存极其有限(比如:iphone4内存只有512M),每个app所能占用的内存是有限制的。
(2) 当app所占用的内存较多时,系统会发出内存警告,这时就得回收一些不需要再使用的内存空间。
比如回收一些不需要使用的对象、变量等。如不及时回收内存,可能造成app闪退、崩溃。
(3) 管理范围:任何继承了NSObject的对象,对其他基本数据类型(int、char、float、double、struct、enum等)无效。
本质原因:OC对象和基本数据类型存放的存储空间是不一样的:
1> 基本数据类型存放在栈区
2> OC对象存放在堆区
先看个例子:
如图,分析:
1> 这里有3个变量(两个int类型,一个指针类型)和一个对象,因此需要占据4块内存空间。
2> 栈区:存放一些局部变量:int类型变量a、b和指针变量p都存放在栈区。
堆区:存放一些动态产生的对象(OC对象):Person类对象存放在堆区。
3》把Person类对象的地址交给指针变量p,指针变量p存放在栈区,这时栈区的指针变量p指向Person类对象。
4》当包含这3个变量代码块执行完毕后,栈区的变量a、b和p所占用的内存空间就会被系统回收(栈区的内存系统会自动回收,系统会检测作用域,作用域一旦没有了,就会自动回收内存)。
5》但是堆区的对象所占用的存储空间是动态分配的,系统是不会自动回收的,因此存在内存泄露。
6》在OC中,即使没有任何指针变量指向堆区的对象,堆区的对象也不会被自动回收,而是由程序员通过代码手动释放的(调用对象的方法)。
2、引用计数器
先了解OC对象的基本结构
(1) 每个OC对象都有自己的引用计数器,是一个整数,表示“对象被引用的次数”,即有多少人正在使用这个OC对象。
(2) 每个OC对象内部专门有4个字节的存储空间来存储引用计数器。(牢记)
3、引用计数器的作用
(1)当使用alloc、new或者copy创建一个新对象时,新对象的引用计数器默认就是1。
(2)当一个对象的引用计数器值为0时,对象占用的内存就会被系统回收。换句话说,如果对象的计数器不为0,那么在整个程序运行过程,它占用的内存就不可能被回收,除非整个程序已经退出。
(3) 判断对象需不需要回收的唯一依据就是计数器,只要计数器不为0,它就占用内存。
4、引用计数器的操作
(1)当使用alloc创建一个新对象时,新对象的引用计数器默认是1
(2) 给对象发送一条retain消息,可以使引用计数器值+1(retain方法返回对象本身)
(3)给对象发送一条release消息,可以使引用计数器值-1
5、对象的销毁
(1) 当一个对象的引用计数器值为0时,那么它将被销毁,其占用的内存被系统回收。
(2) 当一个对象被销毁时,系统会自动向对象发送一条dealloc消息。
(3) 一般会重写dealloc方法,在这里释放相关资源(对象不在了,要释放对象所占用的其它资源),dealloc就像对象的遗言。
(4) 一旦重写了dealloc方法,就必须调用[super dealloc],并且放在最后面调用。
(5) 不要直接调用dealloc方法
(6) 一旦对象被回收了,它占用的内存就不再可用,坚持使用会导致程序崩溃(野指针错误)