【引用】iPhone开发内存管理

转载 2013年12月03日 14:52:12
原文地址:http://www.robinlu.com/blog/archives/392 
开发iPhone 应用程序并不难,基本上就是三个词 - “memory, memory, memory” 。iPhone OS 对内存的要求很严格,有memory leak ,杀掉; 内存使用超限额,杀掉。一个经过测试的程序,在使用过程中90%以上的崩溃都是内存问题造成的。在这里简单总结一下Object-C 内存管理。 
基本概念 
Object-C 的内存管理基于引用计数(Reference Count)这种非常常用的技术。简单讲,如果要使用一个对象,并希望确保在使用期间对象不被释放,需要通过函数调用来取得“所有权”,使用结束后再调用函数释放“所有权”。“所有权”的获得和释放,对应引用计数的增加和减少,为正数时代表对象还有引用,为零时代表可以释放。 
函数 
获得所有权的函数包括 
alloc - 创建对象是调用alloc,为对象分配内存,对象引用计数加一。 
copy - 拷贝一个对象,返回新对象,引用计数加一。 
retain - 引用计数加一,获得对象的所有权。 
另外,名字中带有alloc, copy, retain 字串的函数也都认为会为引用计数加一。 
释放所有权的函数包括 
release - 引用计数减一,释放所有权。如果引用计数减到零,对象会被释放。 
autorelease - 在未来某个时机释放。下面具体解释。 
autorelease 
在某些情况下,并不想取得所有权,又不希望对象被释放。例如在一个函数中生成了一个新对象并返回,函数本身并不希望取得所有权,因为取得后再没有机会释放(除非创造出新的调用规则,而调用规则是一切混乱的开始),又不可能在函数内释放,可以借助autorelease 。所谓autorelease , 可以理解为把所有权交给一个外在的系统(这个系统实际上叫autorelease pool),由它来管理该对象的释放。通常认为交给 autorelease 的对象在当前event loop 中都是有效的。也可以自己创建NSAutoreleasePool 来控制autorelease的过程。 
据苹果的人说,autorelease效率不高,所以能自己release的地方,尽量自己release,不要随便交给autorelease来处理。 
规则 
引用计数系统有自己的引用规则,遵守规则就可以少出错: 
获得所有权的函数要和释放所有权的函数一一对应。 
保证只有带alloc, copy, retain 字串的函数才会让调用者获得所有权,也就是引用计数加一。 
在对象的 dealloc函数中释放对象所拥有的实例变量。 
永远不要直接调用dealloc来释放对象,完全依赖引用计数来完成对象的释放。 
有很多类都提供“便利构造函数(convenience constructors)”,它们创建对象但并不增加引用计数,意味着不需要调用release来释放所有权。很好辨认,它们的名字中不会有alloc和copy。 
只要遵守这些规则,基本上可以消除所有Intrument可以发现的内存泄露问题。 
容器 
类似NSArray, NSDictionary, NSSet 等类,会在对象加入后引用计数加一获得所有权,在对象被移除或者整个容器对象被释放的时候释放容器内对象的所有权。类似的情况还有UIView对subview的所有权关系,UINavigationController对其栈上的controller的所有权关系等等。 
其他所有权的产生 
还有一些用法会让系统拥有对象的所有权。比如NSObject 的performSelector:withObject:afterDelay 。如果有必要,需要显示的调用cancelPreviousPerformRequestsWithTarget:selector:object: ,否则有可能产生内存泄露。 
因这种原因产生的泄露因为并不违反任何规则,是Intrument所无法发现的。 
循环引用 
所有的引用计数系统,都存在循环应用的问题。例如下面的引用关系: 
对象a创建并引用到了对象b. 
对象b创建并引用到了对象c. 
对象c创建并引用到了对象b. 
这时候b和c的引用计数分别是2和1。当a不再使用b,调用release释放对b的所有权,因为c还引用了b,所以b的引用计数为1,b不会被释放。b不释放,c的引用计数就是1,c也不会被释放。从此,b和c永远留在内存中。 
这种情况,必须打断循环引用,通过其他规则来维护引用关系。比如,我们常见的delegate往往是assign方式的属性而不是retain方式的属性,赋值不会增加引用计数,就是为了防止delegation两端产生不必要的循环引用。如果一个UITableViewController 对象a通过retain获取了UITableView对象b的所有权,这个UITableView对象b的delegate又是a, 如果这个delegate是retain方式的,那基本上就没有机会释放这两个对象了。自己在设计使用delegate模式时,也要注意这点。 
因为循环引用而产生的内存泄露也是Instrument无法发现的,所以要特别小心。 
一些和内存管理相关的有用内容:
Objective-C2.0 号称可以支持Garbage Collection了, 也就是垃圾回收, 但是我还没在xcode以及文档中找到相关的用法,也懒得去查了。 关于garbage collection的内容也没啥可说的, 想说说这几天遇到的无GC情况下的几个内存相关问题。 

Objective-C的autorelease确实给开发省了不少事情提高了开发效率, 这对于Mac OSX桌面开发没问题,因为内存大不存在内存紧张的局面。但是如果要为iPhone开发程序, 还是慎用 autorelease的好, 否则只好等程序退出时再清理内存了。 在iphone上最好不要保存不必要的对象, 使用的时候在创建,比如图片、文件等等。 还有一点要注意的就是UITableView, 如果你是把UITableView放在UITableViewCOntroller中,那么别担心,没有什么问题,如果你是在UIViewController或者其子类里放置UITableView,那么注意了, 在Pop掉 viewcontroller的时候一定记得先把UItableView的delegate设置为空, 也就是 [tableView setDelegate:nil] ,之所以这样做, 是因为tableView的delegate是个retain,会保存对象, 所以如果你不在pop之前将delegate设为nil, 将不会调用view controller的dealloc,内存也就无法释放, 这么来几下恐怕就要内存吃紧了。 
总结了几条内存使用经验 
1. 对象现用现创建 
2. 所有用alloc,new , retain等创建的对象都需要调用release去释放, 千万别发送release消息给autorelease对象, 否则只能over了 
3. 注意delegate,如果时retain类型,最好在释放之前将之设为nil 
4. 在频繁使用alloc的地方(循环) 创建自己的NSAutoReleasePool 
5. 对于UIImage对象慎用 [UIImage imageNamed:], 使用[UIImage imageWithContentOfFile:] 或者[image initWithContentOfFile:]

相关文章推荐

iPhone开发中的内存管理

移动开发的特点:资源的有限性。作为手持设备,iphone的内存与传统的PC不可同日而语,这就要求我们在开发IOS程序的过程中,首要也是最重要的任务就是解决内存释放问题,本文将在网络上搜集的关于内存管理...

[iphone开发多线程之]iOS的多核编程和内存管理

本文来源:http://anxonli.iteye.com/blog/1097777 说明:     我也是偶然间看到这篇文章的,之前有很多地方会涉及到异步加载的问题,比如从网上down图片,音视...

Iphone开发基础篇(五)-ObjectC之内存管理

首先简单阐述一下Objective-C内存管理: 1.当你使用new,alloc和copy方法创建一个对象时,该对象的保留计数器值为1.当你不再使用该对象时,你要负责向该对象发送一条release或...
  • xdrt81y
  • xdrt81y
  • 2012年08月06日 21:37
  • 2254

IPhone开发中的内存管理机制

我们在开发中会用到下面的这些相关知识: copy 和 retain 的区别     copy: 建立一个索引计数为1的对象,然后释放旧对象     retain:释放旧的对象,将旧对象的值赋予输...
  • bailu66
  • bailu66
  • 2012年05月03日 12:04
  • 1097

iPhone开发内存管理

开发iPhone 应用程序并不难,基本上就是三个词 - “memory, memory, memory” 。iPhone OS 对内存的要求很严格,有memory leak ,杀掉; 内存使用超限额,...

iphone开发中使用nib(xib)文件的内存管理

在使用nib文件做界面开发的过程中,加载nib文件后,由于设置了outlet和delegate,出现了一些未能及时释放的引用和retain循环,最后结果当然可想而知,dealloc没有走到,内存一路高...

iPhone开发实践中如何去完美解决内存管理问题

本文由YoungShook原创,转载务必在明显处注明:http://blog.csdn.net/youngshook 前段时间和工作室的朋友一起协作开发了一款iOS平台上的软件,在软件完...

iPhone开发内存管理之一

    移动开发的特点:资源的有限性。作为手持设备,iphone的内存与传统的PC不可同日而语,这就要求我们在开发IOS程序的过程中,首要也是最重要的任务就是解决内存释放问题,本文将在网络上搜集的关于...
  • pjk1129
  • pjk1129
  • 2011年05月31日 14:48
  • 2304

IOS]iphone开发之UIImage应用与内存管理,UIImage加载图像方法

UIImage应用与内存管理 用UIImage加载图像的方法很多,最常用的是下面两种:      一、用imageNamed函数  引用         [UII...

iphone开发内存管理之二──静态全局变量的内存问题

     我们在项目中,有时需要一些全局变量存储一些基本信息,那么这些全局的变量内存又是如何管理的呢?下面是网友分享的经验,具体的网址我记不清了,我在这里直接拿过来放到我的博客了,在此向写本文的作者致...
  • pjk1129
  • pjk1129
  • 2011年05月31日 15:12
  • 6731
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【引用】iPhone开发内存管理
举报原因:
原因补充:

(最多只允许输入30个字)