《Objective-C基础教程》第9章 内存管理

第9章 内存管理

9.1 对象生命周期

9.1.1 引用计数

一个对象被从堆中分配出来之后,我们需要明确的知道是谁拥有了这个对象,因为只有拥有这个对象的所有者能够销毁它。但我们在实际使用过程中, 这个对象可能被传递给另一个对象(例如通过传递指针参数),一旦这个过程复杂,我们很难确定谁最后拥有了这个对象。

使用引用计数就可以抛开这个问题,我们不需要再去关心谁拥有了这个对象,因为我们把管理权交割给了对象自己。当这个对象不再被任何人使用时,它自己负责销毁自己。

引用计数器(保留计数器):每个对象都有一个与之相关的整数,当某段代码需要访问一个对象时,该代码就将该对象的保留计数器值加1,表示“我要访问该对象”;反之,则减1,表示不再访问该对象。当保留计数器值为0时,表示不再有代码访问该对象,它将被销毁。

使用alloc、new方法或通过copy消息创建一个对象时,对象保留计数器值置为1。

-(id) retain; 计数加一,返回id类型的值,可以在接受消息同时调用retain
-(oneway void) release; 计数减一
-(NSUInteger) retainCount; 获取计数值

保留计数器值为0将被销毁时,Objective-C会自动发送一条dealloc消息,可以重写dealloc方法来释放特殊的资源,dealloc方法会在对象销毁时自动调用。

9.1.3 访问方法中的保留和释放

一种合理的访问方法

- (void) setEngine: (Engine *) newEngine
{
    [newEngine retain];
    [engine release];
    engine = newEngine;
}

9.1.4 自动释放

自动释放池(autorelease pool),一个存放对象的池(集合),能够自动释放

NSObject类提供了一个autorelease方法:

- (id) autorelease;

该方法预设定了一条在将来某个时间发送的release消息,其返回值是接收消息的对象。当给一个对象发送autorelease消息时,实际上是将该对象添加到NSAutoreleasePool中。当自动释放池被销毁时,会向该池中所有对象发送release消息

示例
- (NSString *) description  
{  
    NSString * description;  
    description = [[NSString alloc] initWithFormat: @"I am %d years old", 4];  
    return([description autorelease]);  
}  
用下面的代码调用  
NSLog(@"%@", [someObject descripion]); 
自动释放池的创建和销毁

自动释放池以栈的形式实现,创建和销毁的代价很小。

  • 通过@autoreleasepool关键字(推荐使用)

    使用@autorelease{}时,任何在花括号里定义的变量在花括号外无法使用

  • 通过NSAutoreleasePool对象

    NSAutoreleasePool *pool=[NSAutoreleasePool new];

    [pool release];//释放该池

在使用AppKit或UIKit的时候,自动释放池会在明确的时间创建或释放,比如在处理当前用户事件的时候。

9.2 Cocoa的内存管理规则

  1. 当使用new、alloc或copy方法创建一个对象时,对象的保留计数器数值为1。当不再使用该对象时,应该向该多想发送release或autorelease消息,销毁对象
  2. 当通过其他方法获得一个对象时,假设该对象的保留计数器的值为1,而且已经被设置为自动释放,则不需要执行任何操作来确保该对象得到清理。如果打算在一段时间内拥有该对象,则需要保留它并确保在操作完成时释放它
  3. 如果保留了某个对象,就需要(最终)释放或自动释放该对象。必须保持retain和release方法的使用次数相等

如果我使用了new,clloc或copy方法获得了一个队,则我必须释放或自动释放该对象。

内存管理规则

获得途径 临时对象 拥有对象
alloc/new/copy 不再使用时释放对象 在dealloc方法中释放对象
任何其他方法 不需要执行任何操作 获得对象时保留,在dealloc方法中释放对象

自动释放池被清理的时间是完全确定的:要么是在代码中你自己动手销毁,要么是使用AppKit时在事件循环结束时销毁。

9.2.3 垃圾回收

Objective-C 2.0引入的自动内存管理机制,也称垃圾回收。

iOS中无法使用垃圾回收的,主要原因是无法知道垃圾回收器什么时候会起作用。

9.2.4 自动引用计数

ARC在编译时进行工作,会在需要的地方自动插入retain和release语句,无需自己动手。

1、 有时用weak会好一些

当指针志向某个对象时,如果管理它的内存(通过retain和release),就拥有这个对象的强引用(strong reference),不管理,拥有弱引用。

保留循环(retain cycle):循环引用导致内存泄漏

弱引用和归零弱引用可以解决这个问题

2、 一辆新车

Xcode可以将已有的项目转换为支持ARC的。但必须禁用垃圾回收机制。

3、 拥有者权限

为了便于ARC工作,必须告诉编译器哪个对象时指针的拥有者

9.3 异常

支持异常特性,需要在Xcode中启用Enable Objective—C Exceptions项。

捕获异常

@try{
} @catch(NSException *exception){
} @finally{
}

抛出异常

@throw theException或 [theException raise]
@try{
    NSException *e=...;
    @throw e;
} @catch(NSException *exception){
    @throw; //rethrow e.
} @finally{
}

这里finally代码块会在@throw引发下一次异常处理调用前执行,@finally是在@throw发生之前调用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章