使用@property和“copy”属性分配NSMutableArray

4

我正在跟随官方教程你的第二个iOS应用程序:Storyboard,它告诉我要像这样声明一个属性masterBirdSightingList(只是一个具体的例子,不需要知道上下文):

@property (nonatomic, copy) NSMutableArray *masterBirdSightingList;

请注意,这里有一个属性copy。然后合成此属性:
@synthesize masterBirdSightingList = _masterBirdSightingList;

接下来有一个init方法让我感到困惑:

- (void)initializeDefaultDataList {
NSMutableArray *sightingList = [[NSMutableArray alloc] init];
self.masterBirdSightingList = sightingList;
[self addBirdSightingWithName:@"Pigeon" location:@"Everywhere"];
}

明确地说,sightingList 是为空间分配的,然后它被分配给 masterBirdSightingList 属性。但是,该属性具有一个 copy 属性。这意味着实例变量 _masterBirdSightingList 将为另一个空间分配以保留来自 sightingList 的内容。为什么?为什么不直接像这样分配属性的空间:

self.masterBirdSightingList = [[NSMutableArray alloc] init];

我想知道语句self.masterBirdSightingList = sightingList是仅仅复制引用还是会分配新的空间来存储内容?谢谢。 - lookof
3
需要注意的是:通常,“可变”对象的-copy方法将返回其不可变版本(在您的情况下为NSArray)。为了避免异常,您需要编写自己的setter方法来调用-mutableCopy。 - David Cairns
1个回答

8
在Objective-C中,属性中的“copy”关键字意味着合成的setter方法将会是这样的:

-(void)setMasterBirdSightingList:(NSMutableArray*)newValue
{
    if (_masterBirdSightingList == newValue) return;
//  NSMutableArray* oldValue = _masterBirdSightingList;
    _masterBirdSightingList = [newValue copy];
//  [oldValue release];    // <-- not applicable in ARC.
}

而那个点语法将始终被翻译为

[self setMasterBirdSightingList:sightingList];

无论属性的特性如何。

"为了从sightingList中保护物品而分配给另一空间"是通过-copy方法完成的。你将参数传递给setter的newValue参数的方式并不重要。


编辑:正如@David在评论中提到的,可变类型的-copy方法返回一个不可变对象。你必须覆盖setter以调用-mutableCopy。参见What's the best way to use Obj-C 2.0 Properties with mutable objects, such as NSMutableArray?.


我希望比较使用isEqual:方法。 - Hot Licks
@HotLicks:不应该将它们与-isEqual:进行比较。==的存在主要是为了避免在-copy返回相同值(对于不可变类型可能会出现这种情况)并且您正在使用self.foo = self.foo时出现双重释放。 - kennytm
1
我查看了教程,并包括说明如何覆盖setter以保留可变性。 - jscs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接