在不使用自引用的情况下设置Objective-C类属性

时间:2009-08-18 18:35:49

标签: objective-c iphone-sdk-3.0

今天早上我在我正在处理的iPhone应用程序中遇到了崩溃,当我修复了这个bug时,我很好奇语法原因这是一个问题。

这是我的代码简化为简单元素。我使用NSArray为项目填充TableView中的项目。 NSArray是一个财产:

@interface FooViewController : UITableViewController {
    NSArray *stuff;
}

@property (nonatomic, retain) NSArray *stuff;

在我的实施文件中:

@synthesize stuff;

- (void)viewDidLoad {     
    NSArray *arr = [[NSArray alloc] initWithObjects:@"", @"Item 1", @"Item 2",   
                                       @"Lorem", @"Ipsum", nil];
    self.stuff = arr;

    [arr release];
}

现在,当我第一次写这个方法的时候,我不小心把它留下了“自我”。这导致了炸弹。虽然在测试时,它一见钟情。我试过了:

stuff = arr;
NSLog(@"%d", [stuff count]);

但在其他轰炸方法中使用 stuff 。现在我已经解决了问题,我可以在其他地方使用[stuff count]。

那么为什么我可以在某些地方使用东西但在其他地方我必须使用 self.stuff

4 个答案:

答案 0 :(得分:5)

当您使用(self)和dot语法时,根据您定义属性的方式(非原子,保留),保留NSArray(stuff)。

如果不这样做,你仍然在进行赋值,但是你不会通过alloc + init保留数组,而不是保留数组,而是立即释放它。

您可以通过“self.stuff = arr”进行分配:

stuff = [arr retain];

但是既然你定义了一个属性,你显然想要使用点语法并为你调用retain。

答案 1 :(得分:4)

这也可以正常运作:

- (void)viewDidLoad {     
    stuff = [[NSArray alloc] initWithObjects:@"", @"Item 1", @"Item 2",   
                                       @"Lorem", @"Ipsum", nil];
}

因为数组是由alloc保留的。但是如果你有一个属性并且使用自动释放数组创建方法,那么通常更好地坚持使用点符号,在这里你可以从属性中“免费”保留:

- (void)viewDidLoad {     
    NSArray *arr = [NSArray arrayWithObjects:@"", @"Item 1", @"Item 2",   
                                       @"Lorem", @"Ipsum", nil];
    self.stuff = arr;

}

您可能只是将其保留为简单,但您还需要在dealloc中释放此数组:

- (void)dealloc {     
  [stuff release]; stuff = nil;
}

答案 2 :(得分:3)

stuff = ...直接引用属性的支持字段。它不会增加保留计数。因此,将对象释放到其他位置可能会将其保留计数降低到零,并在您仍然保持对它的引用时将其取消分配。此外,它可能会导致属性的先前值的内存泄漏 它看起来有时工作的原因是该对象可能尚未由其他人解除分配。

另一方面,self.stuff = ...会向属性的set访问者发送一条消息,该消息将负责保留计数。

答案 3 :(得分:3)

做之间的区别:

stuff=arr;

self.stuff=arr;

在第二种情况下,你实际上调用了自动合成的setStuff:accessor方法,它保留了数组。在您发布的代码中,使用alloc / initWithObjects创建数组,因此它的保留计数为1。

你只需要在viewDidLoad:方法中更改删除对[arr release]的调用,一切都会好的:

- (void)viewDidLoad {     
    NSArray *arr = [[NSArray alloc] initWithObjects:@"", @"Item 1", @"Item 2",   
                                       @"Lorem", @"Ipsum", nil];
    stuff = arr;
}

正如您所注意到的,您还可以使用self.stuff“修复”此问题。我建议不要这样做,因为它模糊了代码的含义,并添加了大多数情况下不需要的额外工作。一般来说,我建议不要使用“自我”。实例方法中的语法。