1

愚蠢的问题,但为什么我们在声明财产时需要使用“保留”?当它被分配一些东西时,它不会被保留吗?

看这个例子,好像一个对象在分配的时候是自动保留的,那么有什么意义呢?

#import "Fraction.h"
#import <stdio.h>

int main( int argc, const char *argv[] ) {
    Fraction *frac1 = [[Fraction alloc] init];
    Fraction *frac2 = [[Fraction alloc] init];

    // print current counts
    printf( "Fraction 1 retain count: %i\n", [frac1 retainCount] );
    printf( "Fraction 2 retain count: %i\n", [frac2 retainCount] );

    // increment them
    [frac1 retain]; // 2
    [frac1 retain]; // 3
    [frac2 retain]; // 2

    // print current counts
    printf( "Fraction 1 retain count: %i\n", [frac1 retainCount] );
    printf( "Fraction 2 retain count: %i\n", [frac2 retainCount] );

    // decrement
    [frac1 release]; // 2
    [frac2 release]; // 1

    // print current counts
    printf( "Fraction 1 retain count: %i\n", [frac1 retainCount] );
    printf( "Fraction 2 retain count: %i\n", [frac2 retainCount] );

    // release them until they dealloc themselves
    [frac1 release]; // 1
    [frac1 release]; // 0
    [frac2 release]; // 0

■输出

分数 1 保留计数:1

分数 2 保留计数:1

分数 1 保留计数:3

分数 2 保留计数:2

分数 1 保留计数:2

分数 2 保留计数:1

释放分数

释放分数


这真让我抓狂!

4

1 回答 1

3

属性的默认行为是 ASSIGN,而不是 RETAIN。这些不是相同的行为。如果您的属性用于原始数据类型,例如 int,则使用 ASSIGN 是正确的。但是,如果您指定 (retain) 并且该属性指向一个对象指针,例如 NSObject *object,则该指针被分配该对象的内存地址,并且它的保留计数加一。如果您的程序仅包含一个单独的 main 函数,那么它的目的就很难看出。但是,假设您的班级有这个方法:

-(void)setMyArrayWithString:(NSString *)s{
    myArray = [NSArray arrayWithObject:s];
    }

假设 myArray 被定义为 NSArray *myArray 并且具有正确的 @property (retain) 语句。在方法返回之前一切正常。这是因为从 NSArray 返回的对象是一个自动释放的对象。如果我们不保留它,它将由 NSAutoReleasePool 释放,我们将无法使用它(并且我们会遇到讨厌的错误和错误的访问冲突)。为了解决这个问题,我们可以做以下两件事之一:

-(void)setMyArrayWithString:(NSString *)s{
    self.myArray = [NSArray arrayWithObject:s];
// OR
    myArray = [[NSArray arrayWithObject:s] retain];    
}

第一个解决方案使用 self.myArray 来利用 @property 定义。此代码分配然后保留对象,以便我们在函数返回时不会丢失它。第二种解决方案手动设置 NSArray *myArray 指针,然后手动保留 NSArray 对象。无论哪种方式, NSAutoreleasePool 都会在函数结束时释放对象,但是它不会被释放,因为我们仍然有我们之前保持它活着的保留。

于 2010-03-12T03:42:22.180 回答