2011-07-03 38 views
5

我已经有了Objective-C类有一个属性需要是集合类(通常是NSArray)的各种情况。有没有一个标准的方式来实现这一点?如果能够使用@synthesize来设置它,那将是非常好的。我可以将属性声明为NSMutableArray和@synthesize,但这不允许我强制哪些类型的对象可以放入集合中,也不会阻止客户端代码修改该数组。我通常做的是这样的:目标C @属性对于多对多关系

@property(nonatomic, readonly) NSArray *widgets; 

- (void)addWidget:(Widget*)widget; 
- (void)removeWidget:(Widget*)widget; 
... 

集合被实现为一个NSMutableArray,包含一个NSArray传递返回给调用者的当前内容。这似乎是很多编码必须是常见的情况。为了建立关键值观测,还需要做更多的编码工作。

我是否错过了一些东西,还是真的需要设置一个集合属性来工作?

回答

1

您可以通过将属性声明为NSArray,但使用NSMutableArray作为存储机制来阻止客户端代码修改您的数组。 @property和@synthesize指令仍然有效。

确实没有一种确保数组返回的对象的类型安全性的好方法,但Objective-C程序员几乎从不担心这一点。它不是一个普遍的问题。如果你真的想确保只有某种类型的对象进入并从数组中出来,你将不得不为NSArray编写一个包装类来完成。

+0

用你描述的方法,我仍然需要编写添加/删除方法,所以我想我可以在那里执行类型。我将不得不测试一下这是否会影响KVO的合规性。我希望这会是因为我现在直接操纵属性的存储变量而不是自己处理单独的可变集合。 – brentopolis

+0

我还注意到,将属性声明为NSArray实际上并不妨碍客户端代码修改数组,因为实际返回的对象是NSMutableArray。它只会导致编译器警告。 – brentopolis

+0

正确的是,当您声明该属性的类型为NSArray时,合成访问器方法仍然会返回内部NSMutableArray对象的retain-auroreleased实例。您的API的用户不应该尝试将该对象转换为NSMutableArray,因为API只承诺NSArray。但是,如果你正在编写一个广泛使用的公共API,这个API很难实施。在这种情况下,您仍然可以使用@synthesize指令,但实现getter方法,以便它返回一个自动释放的伊娃的副本,例如。 'return [[_myMutableArray copy] autorelease];' – Ryan