【问题标题】:Accessing NSManagedObject fields with KVC/valueForKey vs properties - which is better?使用 KVC/valueForKey 与属性访问 NSManagedObject 字段 - 哪个更好?
【发布时间】:2010-06-26 21:20:26
【问题描述】:

使用 CoreData 编写我的第一个应用程序。我用来指导我的书有这样的代码:

// 'Person' is my managed object class
Person *newPerson = [NSEntityDescription
  insertNewObjectForEntityForName:@"Person"
  inManagedObjectContext:self.managedObjectContext];

[newPerson setValue:nameField.text forKey:@"name"];

书中说使用属性样式,例如

newPerson.name = nameField.text;

也可以,但是“看到 Core Data 代码使用 KVC 方法很常见”

对我来说,我找不到使用 KVC 方法的一个理由;魔术字符串只是乞求运行时错误,而且输入更多。

话虽如此,我想现在了解我关于“iPhone 方式”做事的习惯。

这些方法有什么不同吗?如果大多数人使用第一种 KVC 方法,为什么?

【问题讨论】:

  • 达尼和亚当森的 PragProg 书

标签: iphone objective-c core-data coding-style


【解决方案1】:

大多数人不使用我见过的 KVC 方法;我没有,因为你描述的原因。

为了保持理智,请使用 Mogenerator 构建您的访问器:

http://rentzsch.github.com/mogenerator/

它是一个命令行工具,可以生成代理对象,您可以使用这些代理对象来获取 CoreData 对象,并带有一些方便的方法 - 但更好的是,您可以添加自己的方法的某些类别叠加层在您重新执行时不会被破坏从您的数据模型生成类。

XCode 还可以从您的模型生成数据对象,但类更简单(只是访问器),而且我认为 mogenerator 更容易重复使用(这很重要,因为随着时间的推移您会倾向于更改模型)。也许下一个 XCode 在这方面会更好。

我通常将所有数据模型类生成到名为“DataObjects”的类下的子目录中 - 然后每次从导致创建新类的数据模型重新生成类时,您都可以重新添加整个目录(当您有新实体)。示例命令行运行如下所示:

 mogenerator -m ../MyProject.xcdatamodeld/MyProject-v1.xcdatamodel

这将从给定的数据模型生成类到当前目录(在这种情况下,我有一个只有第一个版本的版本化模型)。

【讨论】:

  • 使用 KVC 设置托管对象的属性非常有用。例如,您可以在 NSManagedObject 上创建一个类别,在其中传递一个 JSON 字典,MO 属性将自动填充字典中的值。或者,创建一个扩展 setValue:forKey 的类别,但仅当它与旧值不同时才设置新值。如果您有 NSFetchedResultsControllers 正在监视数据更改并且您不希望您的 tableView 不断地为进/出的虚假更改设置动画,那么这个是必不可少的。
  • 您可以使用 mogen 生成的类创建相同的字典输入类别,mogen 类只是扩展了您可以使用托管对象执行的操作...您还可以调整 mogen 模板以添加比较检查在设置新值之前(尽管我个人认为每次插入或从存储中读取执行该检查的潜在开销将超过偶尔设置重复值所节省的开销)
【解决方案2】:

与直接使用 KVC 相比,属性将导致部分性能提升。然而,KVC 确实有它的用途,尤其是在使用 keyPath 而不仅仅是 key 时。

当您发现或动态访问对象上的值时,KVC 也很有用。

对于日常使用,Kendall 绝对正确,使用 mogenerator 并利用属性。更容易编码、更容易维护等。但是 KVC 绝对有它的位置并且非常有用。

【讨论】:

    【解决方案3】:

    name 是 NSEntityDescription 的属性,所以newPerson.name 没问题。

    但是当您向自定义实体添加自定义属性时,它仅在运行时才知道 - 因此newPerson.favouriteRestaurant 将触发编译时警告,即使它没问题。

    这很烦人。

    摆脱它的一种方法是使用

    [newPerson setValue:@"Crazy Maria's" forKey:@"favouriteRestaurant"]
    

    当您要使用运行时魔法时,这可能是阻止编译器在其他几种情况下唠叨的有用方法。

    【讨论】:

    • 如果需要,您可以在@interface 中添加属性favouriteRestaurant 来关闭编译器。
    • 你的意思是如果你为你的实体添加一个自定义类?
    猜你喜欢
    • 2018-09-26
    • 1970-01-01
    • 2015-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-30
    • 1970-01-01
    • 2014-03-01
    相关资源
    最近更新 更多