Objective-C中内存管理

简介:

 iOS中内存管理

iOS内存管理简介

    Objective-C的内存管理机制与.Net/Java不同,它没有提供全自动的垃圾回收机制,需要我们进行手动管理,其本质相当于在C语言的基础上稍微加了一些自动方法。iOS平台中的内存管理采用了引用计数的管理机制,当创建一个对象使用alloc或者allocWithZone方法时,引用计数就会+1;当释放对象使用release方法时,引用计数就会-1,这意味着每一个对象都会跟踪有多少对象引用它,一旦引用计数为0,该对象的内存就会被释放掉。另外,iOS还提供了一种延时释放机制AutoRelease,以这种方式申请的内存,开发者无需手动释放,系统会在某一时机释放该内存。因此,开发人员在开发应用的时候必须合理的控制何时创建对象、保存对象以及从内存中释放对象。如果使用太多的内存,iPhone会警告应用程序委托和UIViewController,委托收到applicationDidReceiveMemoryWarning:回调,视图控制器会收到didReceiveMemoryWarning,如果继续使用太多内存的话,iPhone将终止你的应用程序,使你的用户回到SpringBoard。很明显,这不是我们所希望得到的用户体验。

iOS内存使用原则:

1.  对象的所有权与销毁

①谁创建,谁释放:如果是以allocnew或者copy创建的对象,则必须调用release或者autorelease方法释放内存,如果没有释放,则导致内存泄漏。除了allocnew,或copy之外的方法创建的对象都被声明了autorelease

②谁retain,谁释放:如果对一个对象发送retain消息,其引用计数会+1,则使用完必须发送releaseautorelease方法释放内存或恢复引用计数,如果没有释放,同样导致内存泄漏。

③没创建且没retain,别释放:不要释放那些不是自己alloc或者retain的对象,否则程序会crash,不要释放autorelease的对象,否则程序会crash

2.   对象的深拷贝与浅拷贝

①深拷贝:复制指针所引用的数据,并将其赋给副本的实例变量。其流程是先创建一个

新的对象且引用计数为1,并用就旧对象的值初始化这个新对象。

ClassA *objA=[[ClassA alloc] init];

ClassA *objB=[objA copy];

objB是一个新对象,引用计数为1,objB的数据等同于objA的数据。

注:objB需要释放,否则会内存泄漏

②浅拷贝:将原始对象的指针复制到副本中,原始对象和副本共享引用数据。其流程是,无需引入新的对象,把原有对象的引用计数+1即可。

ClassA *objA=[[ClassA alloc] init]

ClassA *objB=[objA retain]

注:objB需要释放,恢复objA的引用计数,否则会引起内存泄漏。

3.  对象的存取方法

①属性的声明与实现

变量声明的常用属性类型包括:

readonly属性:只能读,不能写;

assign属性:是默认属性,直接赋值,没有任何保留与释放问题;

retain属性:会增加原有对象的引用计数,并且在赋值前会释放原有对象,然后再进行赋值。

copy属性:会复制原有对象,并在赋值前释放原有对象,然后再进行赋值。

②属性声明可能带来的问题:

当一个非指针变量使用retain(或者copy)这个属性时,尽量不要显性的release这个变量,直接给这个变量置空即可,否则容易产生过度释放,导致程序crash

iOSautorelease机制

1.一般地,在新建一个iPhone项目的时候,xcode会自动在mian函数中为你创建一个autorelease pool,其全名是NSAutoreleasePool,是Objective-C中的一个类。

2.在NSAutoreleasePool中包含了一个可变数组,用来存储被声明为autorelease的所有对象,如果一个对象被声明为autorelease,系统所做的工作就是把这个对象加入到这个数组中去。

3.当AutoreleasePool自身被销毁的时候,它会遍历这个数组,release数组中的每一个成员,如果此时数组中成员的retain count1,那么release之后,retain count0,对象正式被销毁。如果此时数组中成员的retain count大于1,那么release之后,retain count大于0,此对象依然没有被销毁,内存泄漏。

Main函数如下:

int main(int argc,char *argv[])

{

         NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init];

         int retVal=UIApplicationMain(argc,argv,nil,nil);

         [pool release];

         return retVal;

}

4.自动释放池所涉及到的一些常见问题

ios程序开发的时候,会经常遇到在滑动列表,频繁访问图片,频繁打开或关闭数据库的时候,内存会莫名其妙的增长,其实,这些都很有可能是autorelease机制的所导致的。

分析如下:

①滑动列表的时候,内存增长原因:没有使用UITableVIewreuse机制,导致每显示一个cell都用autorelease的方式重新alloc一次,导致cell的内存不断增加。或者,每个cell会显示一个单独的UIView,在UIView发生内存泄漏,导致cell内存不断增长。

②频繁访问图片的时候,内存增长原因:频繁的访问网络图片,导致ios内部API,会不断的分配autorelease方式的buffer来处理图片的解码与显示。

③频繁打开和关闭SQLite数据库,内存增长原因:在进行sqlite频繁打开和关闭操作,而且读取的数据buffer较大,那么sqlite在每次打开关闭的时候,都会利用autorelease的方式分配51k的内存,如果访问次数多,内存马上会顶到几十兆,甚至上百兆,所以,对于频繁读写数据库且数据buffer较大的情况,可以设置sqlite长连接方式,避免频繁打开或关闭数据库。

iOS内存使用误区

2循环引用:循环引用,容易产生野引用,内存无法回收,最终导致内存泄漏。可以通过弱引用的方式打破循环引用链。所谓的弱引用就是不需要retain,直接采取赋值的方式,这样的话可以避免循环引用,同时也要注意避免重复释放的问题。

IOS内存警报处理流程

1. app收到系统发过来的memory warningnotice

2. app释放占用较大的内存;

3. 系统回收此app所创建的autorelease的对象;

4. app返回到已经打开的页面时,系统重新调用viewdidload方法,view重新加载页面数据,重新进行显示;

iOS内存检查工具

1.   编译分析工具Analyze

可以发现编译中的warning,内存泄漏隐患,甚至是逻辑上的问题,从而避免严重的由于内存引起的严重的bug

内存泄漏隐患提示:Potential Leak of an object allocated on line…

数据赋值隐患提示:The left operand of…is a garbage value;

对象引用隐患提示:Reference-Counted object is used after it is release

2.   内存检测工具

①内存泄漏检测工具——Leak

②内存猛增检测工具——Allocations

二者的详细使用,可以自己查阅相关信息进行了解。


总之,对于IOS中内存的管理,需要我们在实际的程序开发中通过编写相应代码,以及调试相关由内存引起的的问题,才可以得到比较好的体会。如果在开发过程中,不能按照分配原则进行内存的合理分配与释放,将会对整个应用程序的性能造成很严重的影响,甚至导致其崩溃。所以开发者必须在深刻理解ios内存管理机制的基础上,采用最佳的内存管理方式,才能获得优良的用户体验。



本文转自HDDevTeam 51CTO博客,原文链接:http://blog.51cto.com/hddev/1112121,如需转载请自行联系原作者


相关文章
|
iOS开发 存储 程序员
|
iOS开发
Objective-C编程 - 1. 浅谈内存分配
Objective-C语言的对象类型都必须用指针,对象所占的内存是在堆(heap)上分配的。 NSString也必须在堆上分配,因此必须用指针。 NSString *someString = @"here is the string";NSString *anotherString = someString; 上面例子的内存分布图如下:   分配在堆中的内存必须直接管理,分配在栈上用于保存变量的内存会在其栈帧弹出时自动清理。
929 0
|
iOS开发
Objective-C 内存管理
Objective-C中,内存对象分二类: 1) 值类型,如 int、float、struct等基本数据类型; 2) 引用类型,通常是指继承自NSObject类的OC对象;   值类型在栈中,由系统自动管理,而引用类型在堆上,需要我们自己手工进行管理 OC中提供了二种内存管理机制: 1)...
770 0
|
Java iOS开发
objective-C 的内存管理之-引用计数
obj-c本质就是"改进过的c语言",大家都知道c语言是没有垃圾回收(GC)机制的(注:虽然obj-c2.0后来增加了GC功能,但是在iphone上不能用,因此对于iOS平台的程序员来讲,这个几乎没啥用),所以在obj-c中写程序时,对于资源的释放得由开发人员手动处理,相对要费心一些。
851 0
|
iOS开发 容器 开发者
objective-C 的内存管理之-自动释放池(autorelease pool)
如果一个对象的生命周期显而易见,很容易就知道什么时候该new一个对象,什么时候不再需要使用,这种情况下,直接用手动的retain和release来判定其生死足矣。但是有些时候,想知道某个对象在什么时候不再使用并不那么容易。
919 0
|
6月前
|
安全 编译器 Swift
IOS开发基础知识: 对比 Swift 和 Objective-C 的优缺点。
IOS开发基础知识: 对比 Swift 和 Objective-C 的优缺点。
394 2