内存管理工作原理
在内存管理的Objective-C代码里,一个Cocoa对象存在于一个生命周期,有明确的阶段。它被创建,初始化,并使用(也就是,其它对象发送消息给它)。它还可能会被保留,拷贝,或压缩,并最终被释放和销毁。下面的讨论以图表形式对一个典型对象的生命周期进行了描述,这里还没有涉及更多的细节。
让我们从后面开始,当垃圾收集被关掉时对象销毁的方式。在此背景下Cocoa和Objective-C 选择一个自动的,策略驱动的过程来保持对象的存在并在不再被需要的时候销毁它们。
这个过程和策略依赖于引用计数的概念。每个Cocoa对象携带一个整数用来指示对其存在感兴趣的其它对象的数目。这个整数被称为对象的保留数(retain count)(“retain”用来避免和术语“reference”重叠)。 当你创建一个对象时,或者通过一个类工厂方法或者使用alloc
或allocWithZone:
类方法, 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一个对象的生命周期- 简化视图
当然,在这个场景中,一个对象的创建者不需要保留这个对象。它早就拥有了这个对象。但是如果这个创建者在一个消息中传递这个对象给另外的对象,情况就发生了变化。在一个Objective-C 程序中,一个接收一些其他对象的对象总是假设在其获得的范围内有效。这个接收对象可以发送消息给被接受的对象以及传递给其他对象。这个假设需要发送对象运转并且不会过早的释放这个对象,当一个客户对象有一个指向它的引用时。
如果客户对象想在接收到的对象程序访问范围之外保留它,可以retain 它- 也就是,发送一个retain
消息给它。保留一个对象增加其保留计数,并由此表达该对象的一个所有权。这个客户对象假设稍后释放该对象的一个职责。如果一个对象的创建者释放它,但是一个客户对象保留了这个相同的对象,这个对象保持存在直到这个客户释放了它。图2-5说明了这个顺序:
Figure 2-5保留一个接收到的对象
和保留一个对象相反,你可以通过给它发送一个copy
或copyWithZone:
消息来拷贝它。(很多子类,如果不是大多数,封装了一些采用或符合这个协议的数据)。拷贝一个对象不仅复制它而且常常总是重置它的保留计数为1(参见图2-6)。拷贝可以是浅拷贝也可以是深拷贝,这依赖于这个对象的本质以及它的预期用途。一个深拷贝复制出一个可以承担成员变量相同作用的对象,而浅拷贝仅仅增加这些成员变量的引用。
谈到使用,区别一个copy
和retain
的是前者声称这个对象的单独使用权;新的拥有者可以改变这个拷贝对象而无须关心它的原始对象。一般而言你拷贝一个对象而不是保留它,当它是一个数值对象- 也就是,一个对象封装了一些基本数据(如整数)。特别是这个对象本身是可变的,比如一个NSMutableString
,对于非可变对象,copy
和retain
可以等同并且也许可以用类似方法来实现。
Figure 2-6拷贝一个接收到的对象
你也许注意到了这个机制关于管理对象生命周期的一个潜在的问题。创建了一个对象并传递给另外的对象的这个创建者对象并不总是知道什么时候可以安全的释放掉这个被创建出来的对象。有可能在堆栈中有这个对象的多个引用,有一些是创建者对象所不知道的。如果这个创建者对象释放掉这个被创建的对象然后其他对象给这个已销毁对象发送消息的话,程序将崩溃。为了消除这个问题,Cocoa 引入了一个延迟释放的机制叫做autoreleasing。
Autoreleasing 使用自释放池(autorelease pools) (以NSAutoreleasePool
类定义)。一个自释放池是一个明确定义了范围的对象集合,这个范围标记着最终什么时候释放。自释放池可以被嵌套。当你发送一个autorelease
消息, 一个该对象的引用被放进最近的自释放池中。它仍然是一个有效的对象,所以其他在自释放池定义范围内的对象可以给它发送消息。当程序执行到范围末尾时,这个池被释放,而且,相应的,池中的所有对象也将被释放(参见图2-7)。如果你在开发一个应用程序你可能不需要建立一个自释放池,因为应用程序工具箱(Application Kit)会自动建立一个范围为应用程序事件周期的自释放池.
Figure 2-7一个自释放池
iPhone OS 提示:因为在iPhone OS 中,应用程序在一个更加内存受限的环境中运行,所以不鼓励在应用程序创建很多对象的方法或代码段中使用自释放池(比如,循环)。相反,你应该在任何可能的时候显式的释放对象。
到目前为止关于对象生命周期的讨论集中在贯穿周期的对象管理机制上。但是一个对象拥有者策略指导如何使用这些机制。这个策略可以总结如下:
· 如果你通过分配并初始化来创建(create)一个对象(比如 [[MyClass alloc] init]
),你将拥有这个对象并负责释放它。这个规则同样适用于使用NSObject 简便方法(convenient method)new
。
· 如果你拷贝(copy)一个对象,你将拥有这个拷贝的对象并负责释放它。
· 如果你保留(retain)一个对象,你拥有该对象部分的所有权并且当你不需要的时候释放它。
相反的,
· 如果你从其他一些对象接收一个对象,你不拥有这个对象并且不应该释放它。(这个规则有一些少数的例外,已在参考文档中显式的标注)
和任何规则集一样,有一些例外和已知问题(“gotchas”):
· 如果你通过类工厂方法创建了一个对象(比如NSMutableArray
arrayWithCapacity:
方法),假设你接收的这个对象是自动释放的。你不应该自己释放这个对象而且如果你想保持其存在的话应该retain它。
· 为了避免循环引用,一个子对象永远不该retain它的父对象。(一个父对象是这个子对象的创建者或者一个以成员变量包含该这个子对象的对象。)
注意:上面指南中的“Release”意味着发送一个release
消息或者一个autorelease
消息给一个对象。
如果你不遵循这个所有权策略,在你的应用程序中很可能会发生两件糟糕的事情。因为你没有释放创建,拷贝,或者保留的对象,你的应用程序将存在内存泄漏。或者当你给一个已从其他地方释放的对象发送消息时导致你的程序崩溃。这里还有一个警告:调试这些问题费时费力。
一个另外的可能发生在一个对象生命周期里的基本事件是归档(archiving)。归档把组成一个面向对象的程序的互相关联的对象网络-对象图-转换成一个持久格式(通常是一个文件),保存了标识和每个图中对象的关系。当程序被解归档时,它的对象图从归档中重新构建。为了参与归档(和解归档),一个对象必须能够编码(和解码)。它的成员变量使用NSCoder 类方法。 NSObject 采用NSCoding 协议来完成这个目的。更多关于对象归档的内容,请参见对象归档(“Object Archives”)。
英文原文链接:http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/
分享到:
相关推荐
### iPhone开发官方指南:内存管理编程指南精要 #### 引言 在软件工程领域,尤其是在移动应用开发中,如iPhone应用开发,内存管理是一项核心技能。它关乎应用的性能、稳定性和用户体验。《iPhone开发官方指南:...
《iPhone应用程序编程指南》是一本面向开发者的重要参考资料,旨在帮助读者深入理解如何为Apple的iOS平台开发应用程序。这本书的中文版使得更多的中国开发者能够轻松掌握iOS应用开发的技术和技巧。 在iPhone应用...
【iOS iPhone开发软件 - 斯坦福大学顶级教程】 这篇教程是基于斯坦福大学的教育资源,专注于iOS应用开发,特别是针对iPhone平台。该教程由经验丰富的教育专家精心编排,旨在帮助初学者和有一定基础的开发者深入理解...
《iPhone开发指南(中-英文版)》是一本详尽阐述如何开发iPhone应用程序的专业书籍,旨在帮助开发者,无论是初学者还是经验丰富的专业人士,都能深入理解iOS平台上的应用开发过程。这本书的内容涵盖了从基础概念到高级...
### 经典教程——iPhone开发指南 #### 一、引言 随着移动互联网的发展,iPhone作为全球最受欢迎的智能手机之一,其应用开发需求日益增长。本文档旨在为初学者提供一个全面且系统的iPhone开发指南,帮助开发者快速...
同时,对性能和内存管理的要求也很高,开发者必须确保应用程序能够高效运行,不会消耗过多的内存或电池。 iPhone应用开发指南还强调了开发过程中所需的各类文档和资料,包括API参考、编程指南以及各种开发工具和...
《iPhone开发基础教程-PDF版》是一份专为初学者设计的全面指南,旨在帮助读者掌握iOS应用开发的基础知识和技能。本教程涵盖了从安装开发环境到创建第一个应用的全过程,深入浅出地讲解了iPhone应用程序开发的核心...
### iPhone开发指南(中文版) #### 一、引言与背景 随着移动互联网技术的飞速发展,智能手机已经成为人们生活中不可或缺的一部分。对于开发者而言,掌握iOS平台的应用开发技能显得尤为重要。苹果公司为了帮助广大...
《iPhone SDK3 开发指南 源代码》 在iOS应用开发的世界中,Apple的iPhone SDK(Software Development Kit)扮演着至关重要的角色。SDK3,是Apple为开发者提供的第三个主要版本,它带来了许多新功能、改进和优化,...
### iPhone人机界面开发指南:构建卓越的用户体验 #### 引言 《iPhone人机界面开发指南》旨在为开发者提供全面、深入的理解,以便在iPhoneOS平台上构建既美观又实用的应用程序。本指南覆盖了从产品定义到最终设计...
- **iPhone开发指南**:提供关于工具使用、设备配置、软件测试等方面的详细指导。 - **Cocoa基本原理指南**:介绍Cocoa框架的设计模式和基本原则,对于理解iPhone应用程序的架构至关重要。 综上所述,“iPhone应用...
### iPhone应用程序开发指南 #### 一、iPhone系统介绍 iPhone是由苹果公司设计并销售的一系列智能手机,自2007年首次推出以来,已经成为全球最受欢迎的智能手机之一。苹果公司的创始人史蒂夫·乔布斯曾表示:...
Cocos2d-iPhone是一个基于OpenGL ES 2.0的2D游戏开发框架,用于iOS平台。1.1-beta版本是该框架的一个早期版本,它提供了丰富的功能和示例,帮助开发者快速创建交互式的游戏和应用程序。这个压缩包包含了一个完整的...
由于所提供的【部分内容】中重复的网址信息较多,且无实质性内容,因此这里重点对标题“iPhone游戏开发实践指南”和【描述】中提及的iPhone游戏开发相关知识点进行详细说明。 ### 知识点概述: #### 1. iPhone与...
接下来,书中会详细讲解C#语言在iOS环境下的特性和差异,比如事件处理、内存管理以及Objective-C与C#之间的交互机制。 书中深入讨论了UI设计和界面控件的使用,如Storyboard、AutoLayout和UIKit组件,帮助开发者...
苹果公司提供的Memory Management Programming Guide(内存管理编程指南)是开发者学习和掌握内存管理规则的重要资源。 ### Objective-C中的内存管理规则 Objective-C的内存管理主要遵循以下原则: 1. **所有权...
从给定的文件信息来看,我们正在探讨的主题是“iPhone开发基础教程-PDF完整版part 3”,然而,由于提供的“部分内容”并没有直接包含具体的教学内容,我们将基于标题和描述来构建相关的知识点,主要围绕iPhone应用...