7

在阅读了Key-Value Coding Programming GuideKey-Value Observing Programming GuideModel Object Implementation Guide,以及阅读了很多关于该主题的 StackOverflow 条目并尝试了各种建模场景之后,我感觉我对如何为我的数据建模。

我最终为我的所有属性和一对一关系使用声明的属性,由私有 ivars 支持。对于需要私有可写的只读属性,我readonly在接口声明中使用该属性,然后在文件中声明的类扩展中使用该属性.h重新声明该属性。在类方法中,我总是使用带点语法的属性访问器,从不直接访问私有 ivars。readwrite.m

然而,有一个方面仍然让我感到困惑:如何正确建模多对关系,特别是当集合是公开不可变但私有可变时(即模型对象的消费者不能向集合添加或删除对象,但是集合的内容由类私下管理)。

我确实了解如何为一对多关系( , 等)实现 KVC 访问器方法,countOf<Key>objectsIn<Key>AtIndex是我迄今为止一直遵循的路线。

但是,我已经看到一些示例代码使用声明的属性来公开关系,不实现 KVC 访问器方法,但仍然是 Key-Value 可观察的。例如:

@interface MyModel : NSObject
{
  // Note that the ivar is a mutable array,
  // while the property is declared as an immutable array.
  @private NSMutableArray *transactions_;
}

@property (nonatomic, retain, readonly) NSArray transactions;

@end

--------------------

@implementation MyModel

@synthesize transactions = transactions_;

- (void)privateMethodThatManagesTransactions
{
  [[self mutableArrayValueForKey:@"transactions"] addObject:t];
}

@end

MyModel如果消费者对象将自己添加为关键路径实例的观察者"transactions",那么每当从集合中添加或删除事务时都会通知它transactions(只要通过该mutableArrayValueForKey:方法完成突变)。

对我来说,这似乎是向许多关系公开的最干净的方式,因为我不需要手动编码集合 KVC 访问器并且它保持代码干净。

但是,这似乎不是 Apple 文档所提倡的方式,我不禁想知道它的工作原理是否只是一个不可靠的副作用。

因此,在为我开始从事的项目在我的真实模型类中使用一种或另一种技术之前,我想获得经验丰富的 Cocoa 开发人员的意见和建议。

所以问题是:如果我使用属性来建模一对多关系,我还需要实现 KVC 访问器/修改器方法吗?

更新

即使我将一个多对多属性声明为readonly,就像上面的示例一样,外部代码仍然可以调用mutableArrayValueForKey:@"transactions"模型对象并改变集合。这似乎表明对多对关系使用声明的属性不是要走的路,但我仍然觉得我不太明白......

4

1 回答 1

6

是的。

然而,有一个方面仍然让我感到困惑:如何正确地建模多对关系,尤其是当集合是公开不可变的,但私下可变时……。

简单:readonly在标头中声明属性,然后在实现文件中将其重新声明为readwrite, copy类扩展

我确实了解如何为一对多关系( , 等)实现 KVC 访问器方法,countOf<Key>objectsIn<Key>AtIndex是我迄今为止一直遵循的路线。

也有变异的。有了这些,你就不需要使用mutableArrayValueForKey:; 相反,您可以直接使用可变访问器。您仍然会收到 KVO 通知,因为 KVO 在第一次将自己添加为属性的观察者时包装了这些方法。

我的博客上有一个访问器选择器格式列表,包括可变访问器。

编辑:

即使我将一个多对多属性声明为只读,就像上面的示例一样,外部代码仍然可以调用mutableArrayValueForKey:@"transactions"模型对象并改变集合。

这是养成使用 mutative 访问器并避免使用mutableArrayValueForKey:. 如果您在尝试时收到编译器警告(没有这样的 [public] 方法),您将不会从类外部发送突变消息。

尽管mutableArrayValueForKey:有人会使用它并且存在风险,但符合 KVO 的属性这里的方法。

于 2009-06-03T19:16:09.573 回答