ios应用开发Objective-C内存管理基础 |
关于我们.net开发人员来说,.net为我们提供了自动内存治理的机制,我们不需去关怀内存的治理 。然而iPhone开发中却是不能的 。这篇文章将简述一下Objective-C的内存治理机制和 步骤和一些 特点 。 手动的进行内存治理 Cocoa和Objective-C的类都是NSObject的子类 。NSObject中有几个 步骤进行内存治理 。alloc 步骤为对象 调配一片内存空间 。dealloc 步骤用于 开释对象的空间 。然而在我们的代码中将永远都不会 使用dealloc 步骤,由于运行时会为你调用此 步骤 开释内存空间 。而你需求做的只不过 引用计数,稍后介绍什么是 引用计数 。 除了alloc和dealloc,NSObject的还有retain和release 步骤两个 步骤用于 引用计数 。retain 步骤给retainCount变量加1,release 步骤给retainCount变量减1 。当 使用alloc为对象 调配一片内存空间的时候,retainCount会为1 。在这个对象的生命周期内,这个对象可能 接续被其它变量 引用 。但有新的变量指向这个对象的时候,你应该调用retain 步骤,这样运行时才会晓得有新的 引用指向了这个变量,在这个对象生存期中 占有它的 使用权 。这个被Objective-C开发人员称之为“ 占有” 。例如:
上面的代码中,myFooTwo通过调用retain 步骤, 获得了Foo对象的 占有权 。在这个对象的生命周期中,会有众多变量来指向和 引用它 。指向这个对象的变量也 可以通过release 步骤来解除这种 占有权 。release 步骤将会告诉运行时,我已经 使用完这个变量了,已经不需求它了,retainCount计数减1 。 当对象的retainCount的计数大于或者等于1的时候,运行时会 接续维持这个对象 。当对象的retainCount为0的时候,运行时会 开释这个对象,并回收它占得内存空间 。 下图 展示了一个Foo对象的生命周期 。Foo对象首先在内存中 调配一个内存空间,而且被myFooOne 引用 。在这个时候Foo对象的retaincount为1 。 Foo * myFooOne = [[Foo alloc] init]; 第二个 引用变量指向Foo对象,这个 引用变量接着调用retain 步骤,其实也是调用Foo对象的retain 步骤 。Foo对象的retaincount变成2 。
接着当myFooOne 引用不需求的时候,通过调用release 步骤,解除与Foo对象的 占有权,Foo对象的retaincount变成1 。
但myFooTwo不在需求的时候,同样通过调用release 步骤,解除与Foo对象的 占有权,Foo对象的retaincount变成0 。 内存泄露 我们 时常会在一个 步骤中申明对象,看下面这个例子:
这上面这个 步骤中,我们为myString 和myFoo 调配了内存空间 。 步骤执行 完毕之后,两个变量超出了作用域的 规模,所以不再有效 。然而这个 步骤并没有releases这两个对象 。所以运行时没有 开释这两个变量占领的内存空间 。除非你的 利用程序 完毕,不然这两个变量占领的内存空间向来都是不可用的 。我们把它称之为内存泄露 。 为了 预防内存泄露 。无论什么时候,我们 缔造一个对象,或者 缔造一个对象的拷贝,我们都必须通过release 步骤 开释 。
弱 引用 看下面的例子:
nyFooTwo指向了Foo对象,然而没有调用retain 步骤,便是一种弱 引用,上面的代码会在运行时报错 。由于myFooOne调用release 步骤 。retaincount变成0,运行时,回收了对象的内存空间 。 而后myFooTwo调用printPutName自然就报错了,见下图 注明 。 总结:本文 方便的介绍了一下手动的进行内存治理、内存泄露、弱 引用等Objective-C的 常识 。 |