愚蠢的问题,但为什么我们需要在声明属性时使用'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
解除分数
解除分数
这让我发疯了!
答案 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都会在函数结束时释放对象,但是它不会被释放,因为我们仍然保留了之前的保留它。