objective-c 2.0属性和'保留'

时间:2010-03-12 03:17:13

标签: objective-c-2.0

愚蠢的问题,但为什么我们需要在声明属性时使用'retain'?当它分配了什么时,它是否会被保留?

看一下这个例子,似乎在分配时会自动保留一个对象,那有什么意义呢?

#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

Fraction 2保留计数:1

第1部分保留计数:3

Fraction 2保留计数:2

第1部分保留计数:2

Fraction 2保留计数:1

解除分数

解除分数


这让我发疯了!

1 个答案:

答案 0 :(得分:3)

属性的默认行为是ASSIGN,而不是RETAIN。这些行为不一样。如果您的属性用于原始数据类型(例如int),则ASSIGN将正确使用。但是,如果指定(保留)并且属性指向对象指针(如NSObject *对象),则会为指针指定对象的内存地址,并将其保留计数加1。如果你的程序只包含一个单独的主函数,那么它的目的很难看出来。但是,假设您的班级有这种方法:

-(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都会在函数结束时释放对象,但是它不会被释放,因为我们仍然保留了之前的保留它。