使用实例变量myArray:
@interface AppController : NSObject
{
NSArray *myArray;
}
有时候我会看到myArray像这样初始化:
- (void)init
{
[super init];
self.myArray = [[NSArray alloc] init];
return self;
}
有时我会用更复杂的方法看到它:
- (void)init
{
[super init];
NSArray *myTempArray = [[NSArray alloc] init];
self.myArray = myTempArray
[myTempArray release];
return self;
}
我知道最终结果没有区别,但为什么人们会费心去做更长的版本呢?
我的感觉是,如果使用@property和@synthesize设置实例变量,则较长的版本会更好(可能因为已经分配了变量)。这是部分原因吗?
感谢。
答案 0 :(得分:2)
如果myArray
是属性并且设置为retain
或copy
(因为它应该属于这样的属性),那么您最终会双重保留变量当你这样做时:
self.myArray = [[NSArray alloc] init];
alloc
调用将引用计数设置为1,属性赋值将保留或复制它。 (对于不可变对象,copy
通常只是对retain
的调用;不需要复制无法更改其值的对象。因此,在赋值后,对象具有保留计数2,即使你只持有一个引用它。这会泄漏记忆。
我希望看到直接分配给实例变量
myArray = [[NSArray alloc] init];
或正确处理保留计数:
NSArray *newArray = [[NSArray alloc] init];
self.myArray = newArray;
[newArray release];
或使用自动释放的对象:
self.myArray = [[[NSArray alloc] init] autorelease]; // Will be released once later
self.myArray = [NSArray array]; // Convenience constructors return autoreleased objects
答案 1 :(得分:1)
这是mutator中使用的习惯用语(有时称为“setter”),但我认为你输错了。通常它看起来像这样:
-(void)setMyName:(NSString *)newName
{
[newName retain];
[myName release];
myName = newName;
}
保留新名称,因为此实例需要保留它;旧名被释放;最后,实例变量被指定为指向新名称。
答案 2 :(得分:0)
我有一种感觉,你的意思是:
NSArray* a = [NSArray arrayWithObjects:@"foo", @"bar", nil];
和这个
NSArray* a = [[NSArray alloc] initWithObjects:@"foo", @"bar", nil];
//...
[a release];
使用第一种样式,静态方法会为您执行alloc / init / autorelease,因此您不必这样做。使用第二种样式,您可以更好地控制释放内存的时间,而不是在退出当前块时自动释放。
答案 3 :(得分:-1)
该代码会使您的应用程序崩溃。第二个版本只复制指针然后释放实例。在发布引用之前,您需要调用[object retain]
。