什么,如果有的话,是基于NSManagedObject的模型层的负面后果?

时间:2011-11-08 15:55:04

标签: iphone objective-c ios core-data ios5

我现在已经在iOS上工作了大约两年,主要是由于简单的数据层(不需要ID,连接,复杂查询等),我总是通过扩展NSObject手动管理持久性,符合NSCoder,并将我的数据保存在平面文件中。

但是,现在我处于需要开始执行更复杂查询工作的位置,而我正在深入研究CoreData。

我现在挂起的是NSManagedObject。这是一个非常令人生畏的课程,我想知道是否有任何不成文的问题我应该注意到这可能会限制我在构建复杂应用程序时的自由。

例如,像@dynamic getter / setters这样的东西不向我清楚等等

所以:

1)NSManagedObject的任何功能是否会阻止我像处理NSObject一样处理自定义类的实例?

2)在没有ManagedObjectContext的情况下处理对象时,NSManagedObject是否有任何异常行为?

3)我可以用自己的自定义getter / setter取代@dynamic属性声明而不会太痛苦吗?我使用了很多自定义setter来强制执行业务逻辑。

依此类推,等等。

由于

3 个答案:

答案 0 :(得分:3)

小心!

核心数据不轻量级。它需要对对象的工作方式进行大量更改,除非它们非常基础。

  

1)NSManagedObject的任何功能是否会阻止我像处理NSObject一样处理自定义类的实例?

故障和托管对象的生命周期有点难以理解。您的对象几乎可以在任何时候“出错”(事件循环的每次迭代),这使得它们失去任何非持久状态。当他们“无故障”时,他们无法访问托管对象上下文之外的任何内容来恢复其状态。托管对象很难访问托管对象上下文之外的任何内容。

瞬态属性是可能的,但几乎限于可以从持久属性计算的事物,因为如果对象出现故障,它们的状态将会丢失。您还必须正式声明您在数据模型中使用瞬态属性。试图设置实例变量会遇到问题。

因此,基本上托管对象属性都必须是持久的或与持久属性相关。查看您计划管理的对象。是否可以将所有实例变量放入持久存储中?如果不是,事情就不会那么简单。您可能在init中设置了实例变量。每次程序运行托管对象时都不会调用init。有awakeFromInsert和awakeFromFetch,但那些不像init那样工作。您的代码调用init并可以传递参数。框架调用awake并且它没有参数。

线程是另一个需要考虑的问题。建议将托管对象上下文及其中的托管对象仅由单个线程使用。如果您有多个线程,并且需要访问模型,则需要创建包含托管对象重复项的重复托管对象上下文。 Core Data旨在解决这个问题,而不会对内存,磁盘I / O和处理器造成太大压力,但从编码角度来看,它并不轻量级。

  

2)在没有ManagedObjectContext的情况下处理对象时,NSManagedObject是否有任何异常行为?

如果没有托管对象上下文,则无法拥有托管对象。

这通常不是问题。托管对象携带指向其托管对象上下文的指针。虽然这可能有点限制。如果模型外部的某些内容需要创建模型对象作为模型的输入,则需要访问托管对象上下文才能执行此操作。希望这将通过某种抽象层,因此它不需要知道它处理核心数据,但你不能只给它一个类并让它具有alloc / init。在不同的托管对象上下文之间移动托管对象也是一项工作。

  

3)我可以用自己的自定义getter / setter取代@dynamic属性声明而不会太痛苦吗?我使用了很多自定义setter来强制执行业务逻辑。

是。这有点复杂但可行。你编写自己的访问者。除了业务逻辑之外,他们还必须调用像willChangeValueForKey:这样的键值观察方法。然后使用原始访问器访问数据。

答案 1 :(得分:1)

  

1)NSManagedObject的任何功能是否会阻止我像处理NSObject一样处理自定义类的实例?

创建和删除它们是不同的,但并不困难。否则,没有

  

2)在没有ManagedObjectContext的情况下处理对象时,NSManagedObject是否有任何异常行为?

我不确定你的意思,你可以将托管对象传递给另一个类,并且在没有其他类知道上下文的情况下非常愉快地使用它,但你必须在某个地方有一个上下文。

  

3)我可以用自己的自定义getter / setter取代@dynamic属性声明而不会太痛苦吗?我使用了很多自定义setter来强制执行业务逻辑。

是的,NSManagedObject就是为此目的而设计的。核心数据编程指南中有大量被覆盖的访问器示例 - 您需要遵循一些规则,但它们并不太繁琐。

核心数据主要是一个持久性框架,而不是一个查询框架 - 我想,一旦你进入它,你会想知道为什么你在所有那些NSCoding实现上浪费你的时间......

答案 2 :(得分:1)

  

1)NSManagedObject的任何功能是否会阻止我   处理自定义类的实例就像我一样   NSObject的?

没有。您可以像NSObject子类一样扩展NSManagedObject子类。

  

2)当对象存在时,NSManagedObject是否有任何异常行为   处理没有ManagedObjectContext?

@dynamic指令将创建优化的访问器,以便保存在由上下文管理的持久存储中。这些值仍然可以像任何其他对象一样可用,但是会产生很多开销。

  

3)我可以用自己的自定义取代@dynamic属性声明吗?   没有太多痛苦的getter / setter?我使用了很多自定义设置器   强制执行业务逻辑。

您可以但是会产生一些性能损失,因为生成的访问器将针对您应用中的特定代码进行高度优化。

关于托管对象的新手混淆的一个主要缺点是缺少通用NSManagedObject可以表示数据模型中的任何实体而没有子类化。 NSManagedObject具有“关联存储”,这基本上意味着它附加了一个打开的字典,可以保存任何键值对。将通用NSManagedObject插入上下文时,关联存储“dictionary”的键将设置为给定实体的属性名称。

因此,您实际上从未真正被迫继承NSManagedObject。这样做很大程度上是为了方便。

这就是为什么您有时会看到使用通用NSManagedObject和setValue:forKey的代码,有时您会看到使用anObject.propertyName的自定义子类。

我还建议,如果您发现自己在上下文之外使用或保存托管对象,那么您设计糟糕的可能性很大。