iphone - 试图了解@property

时间:2011-01-30 17:54:15

标签: iphone

假设我有两个班级。在第一篇中,我在Class1.h

中声明了这一点
@interface Class1 : UIViewController {

  NSString *myString;
  id myObject;

}

在第二节课上我超越了我宣称它就像

@interface Class2 : UIViewController {

  NSString *myString;
  id myObject;

}

@property (nonatomic, retain) NSString *myString;
@property (nonatomic, retain) id myObject;

然后我在Class2.m上 @synthesize myString,myObject

然后,在我的主程序中,我创建了两个对象:一个基于Class1,另一个基于Class2。

class2的@property会有什么影响?是否始终保留分配给Class2上的两个值的每个值?如果是这样,我是否需要“释放”它们?怎么样?

感谢。

2 个答案:

答案 0 :(得分:3)

请阅读Declared Properties section of The Objective-C programming language 有关属性的完整说明;)

在Class2中:

在这种情况下,您将retain属性设置为您的属性,它应该保留在实现中。合成属性时会自动完成此操作。 这意味着你应该

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

一切都应该没问题

在Class1中,您没有属性,因此从外部看不到myString和myObject。但这并不意味着你不应该释放它们。这取决于您初始化它们的方式和/或是否向它们发送保留消息。

顺便说一句,如果你设置assign属性而不释放它,只需在dealloc方法中将其设置为nil即可。如果您将copy设置为它,则必须将其释放。

修改

你说:*但是假设我有这个*

@property (nonatomic, retain) UIView *myView; 

myView = [[UIView alloc] initWithFrame:myFrame]; 
[self.view addSubview:myView]; 
[myView release];

?我已经发布了myView ...我是否必须再次发布它?

首先,由于您以这种方式定义了属性,因此您应该将dealloc方法设置为:

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

所以,答案是不,你不应该释放它,但实际上是不正确的。 请看一下:

myView = [[UIView alloc] initWithFrame:myFrame];  //myView retainCount is 1
[self.view addSubview:myView];  //retainCount is 2
[myView release]; //retainCount is 1 again

稍后在dealloc方法

- (void) dealloc{
    [myView release]; // retainCount becomes 0, is deallocated
    [super dealloc]; // subviews of self.view are released but myView was already deallocated!, so you have over released myView once ;(
}

这是正确的方法:(使用你的属性;))

UIView *aView = [[UIView alloc] initWithFrame:myFrame]; // init, retainCount is 1
self.myView = aView; // retainCount becomes 2
[aView release]; // retainCount becomes 1 again and we are fine.

[self.view addSubview:self.myView]; //retainCounts becomes 2 again.

即使它是2也没有问题,因为当取消分配self.view时,它的子视图也将被释放。因此,当self被释放时,self.myView retainCount将再次变为1。

- (void) dealloc{
    [myView release]; //retainCounts becomes 1
    [super dealloc];  // all its subviews of self.view are released hence myView retaincount becomes 1 and is released corretly
}

有什么区别?

假设self.myView也被其他对象X保留,并且使用前一种方法,X的视图将指向无效对象,因为它已经被释放。

希望有所帮助

<强> EDIT2 作为bbum的指示,这是一个关于属性的迷你短小教程:

当你有

@property (... retain) NSObject *retainVar;
@property (... assign) NSObject *assignVar;
@property (... copy) NSObject *copyVar;

你@synthesize他们

就像拥有以下setter:

// retain
-(void)setRetainVar:(NSObject *)var {
     if (retainVar != var) {
        [retainVar release];
        retainVar = [var retain];
    }
}
//assign
-(void)setAssignVar:(NSObject *)var {
     assignVar = var;
}
//copy
-(void)setCopyVar:(NSObject *)var {
    if (copyVar != var) {
        [copyVar release];
        copyVar = [var copy];
    }
}

(这意味着如果直接分配一个对象,你必须确保它与上面的setter相同,从内存管理的角度来看)

你的dealloc方法应该是这样的:

- (void) dealloc{
    [retainVar release];
    assignVar = nil;
    [copyVar release];
    [super dealloc];
}

设置你的ivars时

例如,在init中:

- (id) init{
    if ((self = [super init])){

        //this is ok
        retainVar = [[NSObject alloc] init];//but is retainVar was not nil we will have a leak ;(

        //This is better
        NSObject *obj = [NSObject alloc] init];
        self.retainVar = obj;
        [obj release]; 

        //this is BAD
        assignVar = [[NSObject alloc] init];//because this is like retaining it, later it will leak

        //below is correct
        NSObject *obj = [[[NSObject alloc] init] autorelease];
        assignVar = obj;

        //copy is pretty much like retain,
        //this is ok
        copyVar = [[NSObject alloc] init]; //but, if copyVar was not nil is a leak!

        //below is better
        NSObject *obj = [NSObject alloc] init]:
        self.retainVar = obj;
        [obj release];

     }
     return self;
}

答案 1 :(得分:1)