【译】苹果官方手册:高级内存管理编程手册2:内存管理方法

内存管理使用的基本模式,引用计数,它的运行环境是由NSObject协议(协议声明程序接口,采用这个协议的类需要实现这个接口)和一个标准方法命名约定提供的。NSObject类同时也定义了一个dealloc方法,这个方法会在对象被释放的时候自动调用。本文将讨论那些在Cocoa程序的内存管理中你必须要了解的基本规则,并会提供一些正确使用的实例。

基本内存管理规则

内存管理的模式是建立在对象的依赖关系上的。任何一个对象都可能被一个或多个对象拥有。当对象被至少一个对象拥有时,这个对象就是存在的。如果一个对象不被任何对象拥有,那么系统将会自动地将这个对象回收。为了确保明确地了解什么时候拥有一个对象什么时候没有,Cocoa定义了如下规则:

  • 当你创建对象时,你拥有它
    当你使用开头为“alloc”、“new”、“copy”或 “mutableCopy” 之类的方法(例如,alloc, newObject 或者mutableCopy)创建一个对象时。
  • 你可以使用retain来保持拥有状态
    当方法接收到一个对象,或者这个方法同时安全地将对象返回给调用者,这个对象通常是有效的。在以下两种情况下,你需要使用retain:(1)在实现一个访问方法或init方法时,你需要保持当前的对象作为一个属性值;或者(2)避免某些操作的副作用导致对象不可用(具体描述参考避免导致你正在使用的对象被释放)。
  • 当你不再需要某个对象时,你必须放弃对对象的拥有权
    你可以通过给对象发送一个release消息或autorelease消息来放弃对象的拥有权。在Cocoa的术语中,放弃一个对象的拥有权被称作“释放”一个对象。
  • 你绝不能放弃一个你没有拥有的对象的拥有权
    根据上方的规则,这条规则是必然的。

一个简单的实例

为了说明这些规则,研究如下代码片段:
{ Person *aPerson = [[Person alloc] init]; NSString *name = aPerson.fullName; [aPerson release]; }
Person对象使用alloc方法被创建,所以当不在需要使用它的时候,我们随后给它发送了release消息。person对象的name属性没有被任何具有拥有性质的函数获取,所以它没有被发送release消息。需要注意的是,这个例子使用的是release而不是autorelease

使用autorelease发送一个延迟释放消息

在你需要发送一个延迟的释放消息时,你可以使用autorelease——典型场景是从方法中返回一个对象。例如,你会这样来实现fullName方法:
- (NSString *)fullName { NSString *string = [[[NSString alloc] initWithFormat:@"%@ %@", self.firstName, self.lastName] autorelease]; return string; }
根据基本规则,你并不拥有stringWithFormat:返回的字符串,所以你可以安全地从这个方法中返回这个字符串。
相比之下,下边的这种实现是错误的:
- (NSString *)fullName { NSString *string = [[NSString alloc] initWithFormat:@"%@ %@", self.firstName, self.lastName]; return string; }
根据命名惯例,没有任何迹象表明fullName的调用者需要拥有返回的字符串。调用者没有义务释放返回的字符串,这将导致内存泄漏。

你并不拥有返回的引用对象

Cocoa中的一些方法生命了对象将以引用的方式返回(它们具有类型为ClassName **id *的返回值)。一个典型的模式是当异常出现时,使用一个包含了异常信息的NSError对象,例如initWithContentsOfURL:options:error:(NSData)和initWithContentsOfFile:encoding:error:(NSString)。
着这些情况下,同样的规则适用于已经被讨论过的情况。当你调用这种方法的时候,你并没有新建NSError对象,所以你并不拥有它。所以你没必要释放他。举例如下:
NSString *fileName = <#Get a file name#>; NSError *error; NSString *string = [[NSString alloc] initWithContentsOfFile:fileName encoding:NSUTF8StringEncoding error:&error]; if (string == nil) { // 解决异常…… } [string release];

实现dealloc方法来放弃对象的拥有权

NSObject类定义了一个方法,dealloc,在当一个对象没有任何拥有者并且内存被回收——在Cocoa术语中叫做“释放”或“反分配”——时自动被调用。dealloc方法所扮演的角色是释放该对象占用的内存,并释放所有它保持的资源,包括其所拥有的对象的实例变量。
下面的实例演示了对Person类的dealloc方法的一种实现:
@interface Person : NSObject @property (retain) NSString *firstName; @property (retain) NSString *lastName; @property (assign, readonly) NSString *fullName; @end

@implementation Person

- (void)dealloc { [_firstName release]; [_lastName release]; [super dealloc]; } @end

重要提醒:绝不要直接调用其它类的dealloc方法。
你必须在实现的最后调用超类的实现。
你不应将系统资源的管理捆绑在对象的生命周期上。参考不要使用dealloc管理稀有资源
当一个应用在终止的时候,对象也许不会发出dealloc消息。因为在推出之前,程序的内存会被自动清理,允许操作系统清理资源比调用所有的内存管理方法更简洁有效。

核心基础类库使用相似但不同的规则

在核心基础类库对象中,内存管理的机制很相似(参考核心基础类库的内存管理程序设计)。但Cocoa和核心基础类库的命名管理是不同的。具体来说,核心基础类库的创建规则(参考创建规则)并不支持返回Objective-C对象的方法。例如,下面的代码片段,你没有责任放弃对myInstance的拥有权。
MyClass *myInstance = [MyClass createInstance];

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容