Objective-C 2.0 with Cocoa Foundation--- 9,内存管理
9.1前言
内存管理在objective-C 2.0中是非常重要的,内存管理做得好不好,最直观的就是反应在你的程序crash上面。想要你的程序健壮稳定,那么请务必搞明白内存管理。
9.2 objective-C 2.0是怎样一个内存机制?
在objective-C 2.0语言中,内存管理主要是基于一个 release count的值来进行判断系统是否要回收该内存。当某对象的 retain count等于0时,系统则会回收这段内存。所以当我们想要释放掉某项目时,我们只需要使其retain count等于0即可。当我们想要hold住该段内存以便后面继续使用(具体怎么用将会在后面提到)那么你只需要保证在你要使用它之前 它的retain count>0即可。为何苹果要这样做?等下告诉你。
首先还是说明 retain count是如何去操作的。假设我们有一个class A:NSObject,然后我们声明一个变量 A *a,不用在意它是临时变量还是类属性变量,这时候它的retain count等于0;当我们给这个变量创建内存空间的时候 我们会使用NSObject类的 alloc 函数:a=[A alloc];这时候 a的retain count则会+1,能使 retain count +1的函数不止有alloc,还有 [a retain],和[a copy],关于这两个函数会在什么时候使用以及他们的区别,将在后面讨论。要想使retain count -1 你需要调用函数 [a release];那么写一串代码来直观的表示retain count的变化:
#import "A.h" /** 略**/ -(void) retainCountDemo { A *a; //retain count of a is 0 a = [A alloc]; //retain count of a is 1 [a retain]; //retain count of a is 2 [a release]; //retain count of a is 1 A* a1 = [a copy]; //retain count of a1 is 1,and a's is 1 too [a release]; //retain count of a is 0, and it will be dealloced [a1 release]; //retain count of a1 is 0, and it will be dealloced return; }
9.3 copy 和 retain的区别?
copy和retain的区别在于它们的字面意思,不同之处在于一个是直接引用(比如说对象的引用),然后retain count+1,另外一个是复制使用(比如说字符串的使用),将复制到的对象a1的retain count+1.
9.4 他们有什么用?
objective-C 2.0是一门面向对象的语言,通过使用 retain count来就可以让开发者在各自的模块中创建使用以后就“释放”,而不用担心影响到其他模块如果同时会使用到该变量而造成的crash。最典型也是最常用的就是我们的NSURLConnection类里面的request,这种异步请求,你并不知道什么时候该释放,因为你没法判断什么时候请求能够返回,所以通过使用retain count 你只关心你创建了一个 NSURLConnction,在设置完接收对象,发送完请求以后你就可以release掉它了,而无需关心内存泄露之类的问题。因为在发送请求的时候,NSURLConnction会将自己retain一次,这时候的retain count变为2,你在自己的函数中调用release的时候retaincount则变为1,而当该请求返回的时候,完成回调函数,会自动调用release一次,这时候NSURLConnction的retain count变为0而释放掉。
通过上面的例子来总结,我们可以发现,其实这是一种延迟释放的机制(好吧,这个词是我自己想到的)。依照这个我们可以解决很多对象共用而不知道该谁去管理内存的问题,苹果的做法就是:管好你自己,你自己alloc+retain多少次,那么请你release多少次。所以,内存管理最基本的就是管好你自己!
9.5 内存管理有没有更简单点的方法呢?
有!但是不建议使用。
方法1:autorelease函数,通过函数名你应该可以知道这个是帮你自动release的。但是需要注意的是这个函数只会自动帮你release1次,你如果在中间使用了retain之类的,所以还请手动release。同时这个有一个致命的缺点,你想用autorelease在class A中创建对象然后传递给class B使用的话这是非常危险的,autorelease是基于系统自带的自动释放池来进行内存管理,系统会每隔一段时间去检测施放池中的对象,并且释放不在使用的对象。当你传递给B的时候,还没来得及使用,被自动释放掉了,那么你的程序又会crash。所以 autorelease通常都是在局部对象中使用。
方法2:IOS 5 ARC(Automatic Reference Counting),苹果终于发现了做IOS开发有太多无证程序猿了,经常因为内存释放不好而导致野指针,内存泄露,各种问题的存在。所以苹果在IOS5的SDK中加了这么一个东西,自动引用计数器。好了,这下各位可以放心的使用,而不用麻烦的去数retain release了。如果你能保证你的客户都会乖乖升级到IOS5的话…… 显然,暂时这东西还不太靠谱……
9.6 稍微高级点的应用:
于是我就只想到一个大量生成的临时对象和自动释放池这两个名词,具体如何使用,请去查阅苹果API,keywords:NSAutoreleasePool。
9.7 后记:
上面所写都是我自己对Objective-C的理解和自己以前所犯错误而总结出来的经验,遗憾的是正好我高考语文考试不及格,所以写的文章也不太好懂,还请见谅,如果有什么疑问或者意见,还请指出一起讨论学习。实例代码,非常简单,如果有朋友看了也不太明白,还请自己写demo验证。对于委托(delegate),通知(notification),属性等这些东西本来是想也在这里说一说的,但是因为思维跳跃比较大,所以还是抽时间另外写出来。
来源: http://www.cnblogs.com/yaski/archive/2012/01/12/2320000.html