OC 内存管理

来源:互联网 发布:质量好的冬装淘宝店 编辑:程序博客网 时间:2024/06/05 18:51

      我们都知道应用程序都是运行在内存中的,但内存资源是有限的,程序不能无限占用内存,这时候对内存进行回收重用就显得很重要。

在java中,java虚拟机在后台有一个程序帮助回收内存,程序员不需要考虑内存管理,但是这个后台程序一直在,就会一占用内存资源。而OC里面没有这种垃圾回收机制,OC很聪明的使用引用计数器来帮助管理内存,为每个OC对象分配四个字节的内存空间来记录对象本身的引用计数。(就像给模特贴上一个数字标签,标签上的数字可以改变)

oc对象的引用计数变化过程

/**增加对象的引用计数*/

Person *xiaoMing = [[Personalloc]init]; //计数器为1

[xiaoMingretain]; // 计数器为2

NSLog( @"%ld", xiaoMing.retainCount);      //打印引用计数器值,当前值为2


/**减少对象的引用计数*/

[xiaoMingrelease]; //计数器减1,当前值为1

NSLog(@"%ld", xiaoMing.retainCount); //打印引用计数器值, 因为release了一次,计数器减1,所以当前值为1

[xiaoMingrelease]; //计数器减1,当前值为0

NSLog(@"%ld", xiaoMing.retainCount); //打印引用计数器值,当前值为0

这时候OC对象的引用计数为0,系统自动调用 dealloc 方法去销毁对象回收内存 (注 :程序员不需要去调用dealloc 函数来销毁对象,系统会自动调用)


有了引用计数,程序员就可以管理OC对象的生命周期,OC也为内存管理提供了两种管理方式,

1、MRC 手动管理  

2、ARC 自动释放池autoreleasepool


MRC : 手动管理

从上面例子可以看出,用 alloc 初始化一个对象的时候,这个对象的的引用计数被置为1,retain(使用copy,new,alloc计数器也会+1)一次引用计数就+1,release一次引用计数就-1;直到引用计数为0的时候,系统销毁对象回收内存。手动管理内存的时候,我们程序员也是同过retain和release 来管理内存. 但是,我们程序员必须清楚的知道对象的作用域,它在哪些地方被使用才能决定对象的生命周期,否则等到你用这个对象时,恰好这个对象被提前释放了,指针指向的内存地址没有对象,变成一个野指针,会引起一些奇妙的错误或程序崩溃。所以,当你使用一个对象,而且不希望它被提前释放,那么就持有它,对它 retain 一次,等到使用完毕的时候再对它进行 release (使用了几次retain,就做相应的几次release)。核心法则就是,谁创建,谁就负责释放,谁对它retain,谁也要释放。


ARC :自动释放池

手动管理内存是个棘手的问题,为此,OC为我们提供了自动释放池autoreleasepool这么一个工具来帮助管理内存。自动释放池,顾名思义就是一个存放对象的池子,自动释放池子中的对象

自动释放池的工作原理 :从上面代码可以看出,对象设置成autorelease(现在Xcode都默认ARC,可以不设置autorelease),放在池子里,池子释放的时候,池子中的对象也跟着被释放。(如果池子不释放,池中的对象也不会释放,可以说对象被延迟释放)

上面的代码没有使用alloc,retain,copy,new,所以我们不需要对它进行内存管理。还有一点需要注意的是,如果对象是单例对象,理论上这个对象永远不会被销毁,只要知道我们不需要对它进释放


说到这里,总结一下内存管理的原则:

1、当你使用new,alloc,copy方法创建一个对象时,该对象的引用计数被置为1,当不再使用这个对象的时候,你要负责向该对象发送一条release消息,使该对象在其使用寿命结束时被销毁

2、当你通过任何其它方式获得一个对象时,你就默认该对象的引用计数为1,而且已经被设置为自动释放,你不需要执行任何操作来确保该对象被清理。除非你打算z在一段时间内拥有该对象,则需要保留它并确保在操作完成使释放它。

3、如果你保留了某个对象,你必须负责在使用完成时释放该对象,必须保证使用retain的次数和release的次数相等。


Cocoa对于临时对象的内存管理

为了降低程序的内存空间占用,Cocoa在程序开始处理事件之前先创建一个自动释放池,并在事件处理完之后销毁该自动释放池,使临时对象的数量保持在最低程度。


清理自动释放池

   有时,自动释放池未能按照通常语气的情况进行清理,比如说,你已经自动释放所有对象,但是程序占用的内存一致保持绝对的增长,来看看下面这段代码

该程序执行一个循环,在循环中每次生成一个自动释放对象,他在循环执行的过程中不会被销毁,这个循环创建了100万个数组对象,所有的这些对象都被放到自动释放池中,因此产生了100万个闲置的对象,这100万个对象一直存在,只有当自动释放池被销毁时他们才会被释放。

解决办法:在循环中创建自己的自动释放池 代码如下

这样一来,循环每执行1000次,销毁自动释放池,同时再创建一个新的自动释放池,池中的对象永远不会超过1000个,程序占用的内存空间就就不会持续增加。需要说明的是:自动释放池以栈的形式实现,当创建一个新的自动释放池时,它将被添加到栈顶,接收autorealese消息的对象被放入最顶端的自动释放次中。所以,如果把一个对象放入自动释放池中,接着创建一个新的自动释放池,然后再释放这个新的自动释放池,这个对象仍然存在,因为它所在的池子没有被销毁



0 0
原创粉丝点击