iPhone内存管理详细解说(二)

19 篇文章 0 订阅
14 篇文章 0 订阅

继上一篇之后,再来讲述iPhone内存管理的细节.

四:动态内存管理

第四节就内容实质来说跟第三节的object的拥有和丢弃政策是一样的,不过是从以代码为引导的动态形式讲述.所以你会在这一节看到许多代码例子帮助你理解.核心还是那些基本的规则.

1.基本知识

主要规则还是object所有权,文档在这里重复性太大,我就只写一些值得注意的地方. 我们会看到很多类提供以”+className…”这种形式的代码(下面有例子),这在文档中叫做”convenience constructors”,记住你用这种方法返回而来的object你是没有所有权的,所以没有责任去释放.

2.一些简单的例子

以下三个例子较为简单地介绍用alloc或convenience constructor或accessor method得到object的区别,看代码:

- (void)printHello {
    NSString *string;
    string = [[NSString alloc] initWithString:@"Hello"];
    NSLog(string);
    [string release];
}

你用alloc得到的string,有义务用release释放.

- (void)printHello {
    NSString *string;
    string = [NSString stringWithFormat:@"Hello"];
    NSLog(string);
}

你用convenience constructor得到的string,放心地不用再管它了.

- (void)printWindowTitle {
    NSString *string;
    string = [myWindow title];
    NSLog(string);
}

你用accessor method得到的string,跟convenience constructor一样,放心地不用再管它了.

3.使用Accessor Methods

官方文档的建议是:相对于频繁的使用retain和release,更好的做法是使用accessor methods.比如我有这么一个object,它的类声明是:

@interface Counter : NSObject {
    NSNumber *count;
}

为了get和set这个count,你要定义两个accessor methods(下面的例子较为简单,详细的accessor methods在后面几节会讲述).get是:

- (NSNumber *)count {
    return count;
}

set稍微复杂点:

- (void)setCount:(NSNumber *)newCount {
    [newCount retain];
    [count release];
    // make the new assignment
    count = newCount;
}

因为你要防止newCount被别人释放了,所以你需要有拥有权,同时把之前你占有所有权的那个count释放掉.

上面提到推荐使用accessor methods,不过在init方法和dealloc里则例外,比如在init里你需要这么写:

- init {
    self = [super init];
    if (self) {
        count = [[NSNumber alloc] initWithInteger:0];
    }
    return self;
}

如果想灵活一点使其可以自己设定值,可以:

- initWithCount:(NSNumber *)startingCount {
    self = [super init];
    if (self) {
        count = [startingCount copy];
    }
    return self;
}

而在dealloc里,则需要释放count:

- (void)dealloc {
    [count release];
    [super dealloc];
}

实现一个reset重置方法: 你可以有两种方法:

(1)使用convenience constructor,很省心地不用再考虑何时释放:

    - (void)reset {
    NSNumber *zero = [NSNumber numberWithInteger:0];
    [self setCount:zero];
}

(2)使用传统的alloc,需要释放:

- (void)reset {
    NSNumber *zero = [[NSNumber alloc] initWithInteger:0];
    [self setCount:zero];
    [zero release];
}

常见错误 (1)不使用accessor methods,那么你经常会忘记retain或release而犯错,如:

- (void)reset {
    NSNumber *zero = [[NSNumber alloc] initWithInteger:0];
    [count release];
    count = zero;
}

(2)实例内存泄漏,如:

- (void)reset {
    NSNumber *zero = [[NSNumber alloc] initWithInteger:0];
    [self setCount:zero];
}

忘记release后,这个zero你再也release不掉了.

(3)release没有所有权的实例,如:

- (void)reset {
    NSNumber *zero = [NSNumber numberWithInteger:0];
    [self setCount:zero];
    [zero release];
}
4.经常引起困惑的情形

(1)使用集合类(如array, dictionary, 或 set)

当添加一个object给集合类的实例时,这个集合类的实例拥有所有权,当这个object从集合类的实例中移除时,或集合类的实例自身被release了,就会释放这个object的所有权.例如创建一个数的array,你可以:

NSMutableArray *array;
NSUInteger i;
// ...
for (i = 0; i < 10; i++) {
    NSNumber *convenienceNumber = [NSNumber numberWithInteger:i];
    [array addObject:convenienceNumber];
}

没必要retain,array就有所有权.当然你也可以:

NSMutableArray *array;
NSUInteger i;
// ...
for (i = 0; i < 10; i++) {
    NSNumber *allocedNumber = [[NSNumber alloc] initWithInteger: i];
    [array addObject:allocedNumber];
    [allocedNumber release];
}

(2)从方法中返回objects

这个很简单了,跟第三节也有重复,直接给出四个情形,你先自己判断一下吧:

- (NSString *)fullName {
    NSString *string = [NSString stringWithFormat:@"%@ %@", firstName, lastName];
    return string;
}



- (NSString *)fullName {
    NSString *string = [[[NSString alloc] initWithFormat:@"%@ %@", firstName, lastName] autorelease];
    return string;
}



- (NSString *)fullName {
    NSString *string = [[[NSString alloc] initWithFormat:@"%@ %@", firstName, lastName] release];
    return string;
}



- (NSString *)fullName {
    NSString *string = [[NSString alloc] initWithFormat:@"%@ %@", firstName, lastName];
    return string;
}

很明显吧,前两个是对的,后两个是扯淡的.若对这个还有疑问,直接回复提问吧.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值