cocoa - "to-many"关系是否应该建模为属性?

标签 cocoa model key-value-observing key-value-coding

在阅读了键值编码编程指南键值观察编程指南模型对象实现指南之后,通过阅读有关该主题的许多 StackOverflow 条目并尝试各种建模场景,我觉得我已经很好地掌握了如何对数据进行建模。

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

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

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

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

@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 访问器,并且它可以保持代码干净。

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

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

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

更新

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

最佳答案

是的。

There is however one aspect which still leaves me puzzled: how to properly model to-many relationships, especially when the collection is to be publicly immutable, but privately mutable ….

简单:将属性声明为 readonly在标题中,然后 redeclare it as readwrite, copy in a class extension在实现文件中。

I do understand how to implement the KVC accessor methods for to-many relationships (countOf<Key>, objectsIn<Key>AtIndex, etc.) and this is the route I've been following so far.

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

我有a list of the accessor selector formats ,包括变异访问器,在我的博客上。

编辑:

Even when I declare a to-many property as readonly, like in the example above, external code can still call mutableArrayValueForKey:@"transactions" on the model object and mutate the collection.

这是养成使用变异访问器并避免 mutableArrayValueForKey: 的习惯的一个很好的理由。 。如果您每次尝试时收到编译器警告(没有这样的[公共(public)]方法),您将不会从类外部发送突变消息。

尽管 mutableArrayValueForKey: 可用以及有人使用它的风险,符合 KVO 的属性是这里的选择。

关于cocoa - "to-many"关系是否应该建模为属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/946474/

相关文章:

macos - 特定的 PNG 压缩类型是否与 macOS Cocoa 应用程序不兼容?

ios - 操作字符串数组以在末尾获得 +1

cocoa - 使用命令 Alt NSKeyEquivalent 注册 NSService

java - 如何在javax.print中获取打印机的型号?

python - Django 模型 : mutual references between two classes and impossibility to use forward declaration in python

ios - Swift 中的 KVO,observeValueForKeyPath 的有趣问题

swift - 如果 View Controller 已快速订阅通知,如何进行单元测试

javascript - 绕过WebView跨域安全

javascript - javascript类方法定义计算带配料的食品价格的最佳实践

swift - Swift 4 中的 KVO 监听器问题