开
发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无法发现的,所以要特别小心。
苹果开发工具XCode教学:用Instruments解决内存泄露问题
via http://www.cocoachina.com/index.php/archives/cocoachina_113.html
很好用的开源分析源码BUG工具:http://clang-analyzer.llvm.org/
相关推荐
### Cocoa内存管理程序教程知识点详解 #### 一、前言 Cocoa框架是苹果公司为开发者提供的用于构建macOS及iOS应用的重要工具集之一。它不仅提供了丰富的API来帮助开发者快速构建应用程序,还包含了对内存管理的支持...
- **Cocoa内存管理**: 讲解对象所有权策略及其相关技术,如对象的创建、复制和销毁。 #### 九、用户事件处理 在Mac OS X 10.2之前的版本中,由于用户事件的生成方式不同,导致Cocoa和Carbon应用程序之间存在差异。...
内容:“内存管理规则”总结...“Cocoa 中 Core Foundation 对象的内存管理”介绍了Cocoa代码中Core Foundation对象的内存管理技术及使用指南。“Nib 对象的内存管理”讨论了与nib文件相关的内存管理的问题。pdf格式。
总之,深入理解Cocoa框架意味着要掌握Objective-C的基础,包括内存管理、面向对象编程,以及Cocoa特有的设计模式和技术。只有这样,才能在苹果平台上构建出高效、稳定且用户体验优良的应用程序。
8. **内存管理**:无论是Objective-C的引用计数还是Swift的自动引用计数,理解内存管理对于避免内存泄漏和提高性能至关重要。 9. **测试与调试**:Cocoa开发包括Xcode内置的测试框架和调试工具,帮助开发者确保代码...
- **内存管理**:在Objective-C中,内存管理是一项重要的任务。本书将介绍ARC(Automatic Reference Counting)自动引用计数机制以及如何手动管理对象生命周期的方法。 #### 五、实践案例分析 - **创建简单的Mac ...
3. **Foundation框架**:这是Cocoa的基础,提供了许多基础数据类型、集合类、字符串处理、线程管理等基本服务。理解Foundation框架对于使用Cocoa进行开发至关重要。 4. **AppKit和UIKit**:在Mac OS X上,Cocoa的...
本书首先会引导读者了解Objective-C的基础,包括语法、类、对象以及内存管理。然后,它会深入Cocoa的核心组件,如Foundation框架和AppKit(针对macOS)或UIKit(针对iOS),解释这些组件如何协同工作来构建应用的...
《Objective-C高级编程:iOS与OS X多线程和内存管理》是一本深入探讨Apple平台开发中的关键技术的书籍。本书主要围绕Objective-C语言在iOS和OS X操作系统上的应用,特别是针对多线程和内存管理这两个核心主题进行...
1. **内存管理**:包括对象生命周期、引用计数(Objective-C中的ARC)和Swift中的强引用、弱引用和无主引用等概念,以及如何避免内存泄漏和过度分配。 2. **线程与并发**:多线程在iOS和macOS开发中至关重要,学习...
9.3 Cocoa内存管理规则138 9.3.1 临时对象138 9.3.2 拥有对象139 9.3.3 垃圾回收141 9.4 小结142 第10章 对象初始化143 10.1 分配对象143 10.2 初始化对象143 10.2.1 编写初始化方法144 10.2.2 初始化时做什么146 ...
14. **Performance优化**:了解内存管理(ARC)、GCD(Grand Central Dispatch)以并行处理任务,以及 Instruments 工具进行性能分析,都是提升Cocoa应用性能的关键。 以上就是“Swift Cocoa编程教程”中可能涵盖的...
- **自动引用计数 (ARC)**:Objective-C 4.0 引入了 ARC 特性,它可以自动管理内存,减少开发者因手动管理内存而产生的错误。 - **块 (Blocks)**:块是 Objective-C 中一种类似匿名函数的概念,可以用来简化回调函数...
- **内存管理**: 早期版本的Objective-C需要手动管理内存,后来引入了ARC(Automatic Reference Counting)技术,简化了内存管理。 ### 五、Cocoa编程实践 Cocoa编程不仅仅是理论上的学习,更重要的是动手实践。下面...