对于NSMutableSet类型的属性使用retain vs. copy的语义是什么?

时间:2010-09-30 15:49:26

标签: objective-c memory-management copy retain

我一直在使用最优秀的Accessorizer来自动神奇地为Xcode中的Obj-C代码生成setter / getter。最近在Accessorizer中进行了更改:

旧版本的Accessorizer:
@property(非原子,保留)NSMutableSet * setA;
@property(nonatomic,retain)NSMutableSet * setB;

新版本的配置器:
@property(非原子,复制)NSMutableSet * setA;
@property(非原子,复制)NSMutableSet * setB;

可悲的是,新版本崩溃了我的代码。在我的代码中,我执行以下操作:

self.setA = [[[NSMutableSet alloc] init] autorelease];
self.setB = [[[NSMutableSet alloc] init] autorelease];

// ...

[self.setA minusSet:self.setB];  

上面的代码行使用旧方法(保留)可以正常工作,但使用新方法(副本)崩溃。显然这里有些不对劲。我广泛依赖Accessorizer。有人可以澄清在NSMutableSet的上下文中使用copy / retain的含义吗?

谢谢,
道格

2 个答案:

答案 0 :(得分:4)

如果您的属性类型是可变集,那么您很可能需要保留。如果它是非可变集(又名NSSet),Apple的指导方针说使用复制而不是保留。

区别在于期望可变集合会发生变化。一个非可变集合应该保持不变,但如果它被声明为retain,有人可以将它设置为一个可变集合,然后意外地更改内容。

答案 1 :(得分:4)

是的,这是属性的“特征”。当您设置声明为copy的属性时,生成的setter将在对象上调用-copy。不幸的是,在可变对象的情况下,这会产生不可变的变体。

换句话说,[myMutableSet copy]返回的对象可变。

如果您需要将该集设置为可变,那么必须使用retain(或覆盖设置器以使用mutableCopy而不是copy)。< / p>

我在此处提交了一个错误(rdar:// 8416047),但它被关闭为“按设计工作”。 (因为setter确实无法知道对象是否可变)