`
hulunberbus
  • 浏览: 858071 次
文章分类
社区版块
存档分类
最新评论

iPhone开发指南-内存管理

 
阅读更多

内存管理工作原理

在内存管理的Objective-C代码里,一个Cocoa对象存在于一个生命周期,有明确的阶段。它被创建,初始化,并使用(也就是,其它对象发送消息给它)。它还可能会被保留,拷贝,或压缩,并最终被释放和销毁。下面的讨论以图表形式对一个典型对象的生命周期进行了描述,这里还没有涉及更多的细节。

让我们从后面开始,当垃圾收集被关掉时对象销毁的方式。在此背景下CocoaObjective-C 选择一个自动的,策略驱动的过程来保持对象的存在并在不再被需要的时候销毁它们。

这个过程和策略依赖于引用计数的概念。每个Cocoa对象携带一个整数用来指示对其存在感兴趣的其它对象的数目。这个整数被称为对象的保留数(retain count)(“retain”用来避免和术语“reference”重叠)。 当你创建一个对象时,或者通过一个类工厂方法或者使用allocallocWithZone:类方法, Cocoa 做了一些很重要的事情:

· 它设置对象的isa指针- NSObject类的唯一公共成员变量-以指向这个对象的类,这样把这个对象集成到运行时视图类层次。(参见对象创建“Object Creation”获取更多信息)

· 它设置对象的保留数(retain count- 一种由运行时管理的隐藏的成员变量- 1。(这里假设一个对象的创建者对其存在感兴趣)

在对象分配后,你一般会设置它的成员变量为一个合理的初始值。 (NSObject声明init方法作为这个目的的原形) 这个对象现在已经可以使用了;你可以发送消息给它,把它传递给其他对象,等等。

注意:因为一个初始化器可以返回一个不是显式声明的那个对象,惯例是嵌套alloc消息表达式在init消息里(或者其他初始化器)- 比如:

id anObj = [[MyClass alloc] init];

当你释放一个对象- 也就是,发送一个release消息给它 - NSObject减少其保留数。如果这个保留数从1变成0,这个对象会被释放。释放分成两个步骤。首先,对象的dealloc 方法被调用来释放成员变量并动态释放分配的内存。然后操作系统销毁对象自身并回收该对象曾经占用的内存。

重要:你永远不该直接调用一个对象的dealloc方法。

要是你不想一个对象马上消失?如果你在从别处接收到一个对象时给它发送了一个retain消息,这个对象的保留数(retain count)被增加为2。现在在释放之前需要两个release消息。2-4图示了这个相对简化的场景。

Figure 2-4一个对象的生命周期- 简化视图

object_lifecycle_1

当然,在这个场景中,一个对象的创建者不需要保留这个对象。它早就拥有了这个对象。但是如果这个创建者在一个消息中传递这个对象给另外的对象,情况就发生了变化。在一个Objective-C 程序中,一个接收一些其他对象的对象总是假设在其获得的范围内有效。这个接收对象可以发送消息给被接受的对象以及传递给其他对象。这个假设需要发送对象运转并且不会过早的释放这个对象,当一个客户对象有一个指向它的引用时。

如果客户对象想在接收到的对象程序访问范围之外保留它,可以retain - 也就是,发送一个retain消息给它。保留一个对象增加其保留计数,并由此表达该对象的一个所有权。这个客户对象假设稍后释放该对象的一个职责。如果一个对象的创建者释放它,但是一个客户对象保留了这个相同的对象,这个对象保持存在直到这个客户释放了它。图2-5说明了这个顺序:

Figure 2-5保留一个接收到的对象

object_lifecycle_2

和保留一个对象相反,你可以通过给它发送一个copycopyWithZone:消息来拷贝它。(很多子类,如果不是大多数,封装了一些采用或符合这个协议的数据)。拷贝一个对象不仅复制它而且常常总是重置它的保留计数为1(参见图2-6)。拷贝可以是浅拷贝也可以是深拷贝,这依赖于这个对象的本质以及它的预期用途。一个深拷贝复制出一个可以承担成员变量相同作用的对象,而浅拷贝仅仅增加这些成员变量的引用。

谈到使用,区别一个copyretain的是前者声称这个对象的单独使用权;新的拥有者可以改变这个拷贝对象而无须关心它的原始对象。一般而言你拷贝一个对象而不是保留它,当它是一个数值对象- 也就是,一个对象封装了一些基本数据(如整数)。特别是这个对象本身是可变的,比如一个NSMutableString,对于非可变对象,copyretain可以等同并且也许可以用类似方法来实现。

Figure 2-6拷贝一个接收到的对象

object_lifecycle_3

你也许注意到了这个机制关于管理对象生命周期的一个潜在的问题。创建了一个对象并传递给另外的对象的这个创建者对象并不总是知道什么时候可以安全的释放掉这个被创建出来的对象。有可能在堆栈中有这个对象的多个引用,有一些是创建者对象所不知道的。如果这个创建者对象释放掉这个被创建的对象然后其他对象给这个已销毁对象发送消息的话,程序将崩溃。为了消除这个问题,Cocoa 引入了一个延迟释放的机制叫做autoreleasing

Autoreleasing 使用自释放池(autorelease pools (以NSAutoreleasePool类定义)。一个自释放池是一个明确定义了范围的对象集合,这个范围标记着最终什么时候释放。自释放池可以被嵌套。当你发送一个autorelease消息, 一个该对象的引用被放进最近的自释放池中。它仍然是一个有效的对象,所以其他在自释放池定义范围内的对象可以给它发送消息。当程序执行到范围末尾时,这个池被释放,而且,相应的,池中的所有对象也将被释放(参见图2-7)。如果你在开发一个应用程序你可能不需要建立一个自释放池,因为应用程序工具箱(Application Kit)会自动建立一个范围为应用程序事件周期的自释放池.

Figure 2-7一个自释放池

autoreleasepool

iPhone OS 提示:因为在iPhone OS 中,应用程序在一个更加内存受限的环境中运行,所以不鼓励在应用程序创建很多对象的方法或代码段中使用自释放池(比如,循环)。相反,你应该在任何可能的时候显式的释放对象。

到目前为止关于对象生命周期的讨论集中在贯穿周期的对象管理机制上。但是一个对象拥有者策略指导如何使用这些机制。这个策略可以总结如下:

· 如果你通过分配并初始化来创建(create)一个对象(比如 [[MyClass alloc] init]),你将拥有这个对象并负责释放它。这个规则同样适用于使用NSObject 简便方法(convenient methodnew

· 如果你拷贝(copy)一个对象,你将拥有这个拷贝的对象并负责释放它。

· 如果你保留(retain)一个对象,你拥有该对象部分的所有权并且当你不需要的时候释放它。

相反的,

· 如果你从其他一些对象接收一个对象,你不拥有这个对象并且不应该释放它。(这个规则有一些少数的例外,已在参考文档中显式的标注)

和任何规则集一样,有一些例外和已知问题(“gotchas”):

· 如果你通过类工厂方法创建了一个对象(比如NSMutableArrayarrayWithCapacity:方法),假设你接收的这个对象是自动释放的。你不应该自己释放这个对象而且如果你想保持其存在的话应该retain它。

· 为了避免循环引用,一个子对象永远不该retain它的父对象。(一个父对象是这个子对象的创建者或者一个以成员变量包含该这个子对象的对象。)

注意:上面指南中的“Release”意味着发送一个release消息或者一个autorelease消息给一个对象。

如果你不遵循这个所有权策略,在你的应用程序中很可能会发生两件糟糕的事情。因为你没有释放创建,拷贝,或者保留的对象,你的应用程序将存在内存泄漏。或者当你给一个已从其他地方释放的对象发送消息时导致你的程序崩溃。这里还有一个警告:调试这些问题费时费力。

一个另外的可能发生在一个对象生命周期里的基本事件是归档(archiving)。归档把组成一个面向对象的程序的互相关联的对象网络-对象图-转换成一个持久格式(通常是一个文件),保存了标识和每个图中对象的关系。当程序被解归档时,它的对象图从归档中重新构建。为了参与归档(和解归档),一个对象必须能够编码(和解码)。它的成员变量使用NSCoder 类方法。 NSObject 采用NSCoding 协议来完成这个目的。更多关于对象归档的内容,请参见对象归档(“Object Archives”)。

英文原文链接:http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/

分享到:
评论

相关推荐

    iphone开发官方指南-内存管理编程指南

    有大大弄成docx格式,我转换成pdf格式再次上传

    iPhone应用程序开发指南.中文.pdf

    虚拟内存系统 13 自动休眠定时器 14 应用程序的程序包 14 信息属性列表 16 应用程序图标和启动图像 21 Nib文件 21 处理关键的应用程序任务 22 初始化和终止 22 响应中断 23 观察低内存警告 25 定制应用程序的行为 25...

    IOS开发-开发心得-技术栈-初学者-学习路线-开发原则

    它强调了深入了解iOS生态系统、精通编程语言、熟悉开发工具、掌握核心框架、适配不同设备和屏幕、遵循设计准则、注重性能和内存管理、测试和调试、遵循App Store审核规则以及持续学习和更新等方面的重要性。...

    《iOS6开发指南》精彩书摘

    iOS中开发性能优化方法,其中包括:内存优化、资源文件优化、延迟加载、持久化优化、使用可重用对象、多线程以及程序编译参数等方面介绍性能优化。 第18章“管理好你的程序代码——代码版本控制”。学习如何使用Git...

    iOS 5 arc 指南

    iOS arc开发指南,很好的一本书,使用此方法后不用再手动释放内存空间,很好的防止内存泄露

    Android移动应用开发(第3版)卷Ⅰ基础篇 (Shane Conder, Lauren Darcey) PDF扫描版

    附录还包含了Android开发常用工具(模拟器、DDMS和Eclipse)的使用指南。  《Android移动应用开发(第3版)卷Ⅰ:基础篇》卷Ⅰ以及本书的卷Ⅱ,不仅适合Android应用程序开发人员阅读,还能为QA测试人员提供指导。另外,...

    Objective-C入门指南.pdf

    这篇教程是建立在假设你已经有一些基本的C语言知识,包括C数据类型、什么是函数、设么是返回值、关于指针的知识以及基本的C语言内存管理。如果您没有这些背景知识,我非常建议你读一读K&R的书:The C Programming ...

    iOS 开发入门必备资料

    iOS人机界面指导手册.pdf Cocoa基本原理指南.pdf iOS技术概览.pdf 核心动画编程指南.pdf 多线程编程指南.pdf 初窥Xcode4 -- Xcode4主题样式、...内存管理编程指南.pdf Cocoa 编码指南.pdf Objective-C培训资料.pdf

    Android程序设计基础

    书中还结合数独游戏等实例更加形象生动地讲解了 android开发的基本流程,且每章最后都有一个 “快速阅读指南 ”,更加方便了读者的阅读。.  本书内容完整丰富,具有较强的通用性,读者都能通过本书快速学习 ...

Global site tag (gtag.js) - Google Analytics