原文地址: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开发内存管理相关推荐

  1. iPhone开发内存管理

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

  2. iPhone开发内存管理之一

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

  3. iphone开发--内存管理

    内存管理是iphone开发中很重要的一个环节,没有处理好会是系统出现很多问题, 很严重的一个就是直接导致程序闪退.因此,内存管理是很让新手头疼的,也是新手晋 级为菜鸟必走的一个环节.今天讨论的主题就是 ...

  4. iphone开发 内存管理

    我一般喜欢在开发的最后阶段,才考虑内存管理 那么就需要好的工具,帮你定位,内存泄露的位置. 经过一段时间的研究,已经完美控制了内存的增长 1.通过查找alloc关键字,自己找出项目中需要释放的内存 2 ...

  5. 引用 软件开发公司管理手册

    引用 uvsoftlifeng 的 软件开发公司管理手册 一.动态平衡与发展 公司创办的热情.首轮机会过去后,面对经营中不断出现的诸多问题,经营者的想法会发生很多变化,会发现可以导致公司走向衰落甚至垮 ...

  6. iOS开发内存管理总结

    一.retain.copy.assign的区别: 1.retain:当对一个对象A调用retain,然后赋值给B时,对象的引用计数加1,A和B指向同一个内存地址. 2.copy:当对一个对象A调用re ...

  7. iphone objective-c内存管理

    1:retain返回一个id类型的值,通过这种方式,可以嵌套执行带有其他消息带有参数的保留调用,增加对象的保留计数器值,并要求对象执行某种操作,例如:[[car retain]  setTire:ti ...

  8. iphone内存管理的具体问题解决方案

    iPhone 开发内存管理 开发iPhone 应用程序并不难,基本上就是三个词 - "memory, memory, memory" .iPhone OS 对内存的要求很严格,有m ...

  9. iPhone内存管理详细解说(一)

    iPhone内存管理详细解说系列转载来源:http://keywind.me/blog/2011/05/07/iphonenei-cun-guan-li-xiang-xi-jie-shuo-yi/ 感 ...

最新文章

  1. python内存管理错误的是_关于Python内存管理,下列说法错误的是
  2. .NET微服务体系结构中为什么使用Ocelot实现API网关
  3. api 数据gzip压缩_如何使用GZip和Jersey压缩Java REST API中的响应
  4. 使用Lucene的新FreeTextSuggester查找长尾建议
  5. Qt文档阅读笔记-Qt工作笔记-QThread解析与实例(主线程发送信号给子线程)
  6. 消息称快手拟发行4.159亿股 招股价上限约93港元
  7. Android 四大组件学习之Service五
  8. java 中文乱码转换_java中文乱码怎么转换
  9. 【PageHelper分页】实现拦截pageNum和pageSize
  10. PGP Shredder的使用,加密解密
  11. 字幕制作 分享剪辑视频添加滚动字幕的操作步骤
  12. vue + openlayers鼠标移动获取地图经纬度格式化的两种方式
  13. [hive 报错]:FAILED:SemanticException [Error 10025] Expression not in GROUP BY key
  14. html基础之好看的header
  15. java 简单的聊天室_Java简单聊天室
  16. 常用的设计模式(七)——门面设计模式
  17. 浏览器网页谷歌翻译-使用js脚本
  18. [ASPX]常用笔记
  19. FreeFileSync 同步自动备份RealTimeSync(自动同步工具)
  20. python排课系统_关于排课系统的实现?

热门文章

  1. 全国计算计算机应用能力考试合格证,全国计算机应用能力考试证书有效期
  2. Cesium实战专栏09.Cesium动态立体墙
  3. 从教育的视角观察中秋节
  4. 如何避免虚拟主机空间中的黑名单问题?
  5. python3中os.system(cmd)的返回值
  6. Vue中如何使用vant(Vue2的版本)
  7. 怎么给计算机主机设置密码,怎么给电脑设置密码,详细教您电脑怎么设置密码...
  8. 考研政治全年复习规划
  9. zabbix告警收敛
  10. 微信公众号JSAPI分享功能踩坑记录