在核心数据中使用可变类型作为可转换属性的危险

至此,我们已经建立了数据模型。 现在介绍建立符合NSCoding的可变数据类型’ UnpredicatbleValue ‘的部分。 此数据类型具有一个变量存储的属性,称为Int类型的’ value 实现如下:

现在,我们可以为我们的TransformableContainer实体创建NSManagedObject子类。 该类的实现如下:

现在,请仔细阅读以下说明。

注意 :如果将托管对象引用的值/对象替换为全新的值/对象 ,则Core Data会将托管对象视为已更改。 据说, 管理对象有未决的更改 。 现在,在上下文中调用save时,将保存下一次具有待处理更改的受管对象。
但是,如果您有一个由托管对象指向的对象,并且更改了objects 变量 (更改了对象的状态),则Core Data不知道它已被更改 。 因此, 托管对象未标记为具有挂起的更改 。 下次在上下文中调用保存时,将不会保存此类对象。

如果您已阅读以上说明,我们现在可以通过实际测试来证明这一点。 让我们打开ViewController.swift并编写以下代码:

如您所见,我们在viewDidLoad()中执行以下操作

  • appDelegate的persistentContainer获取viewContext
  • 在第一个do块中,我们将TransformableContainer插入到viewContext中。设置为3 ,然后在viewContext上执行保存
  • 在第二个do块中,我们获取TransformableContainer。更改为4并执行保存。
  • 在第三个do块中,我们获取TransformableContainer。 打印值。
  • 在第四个do块中,我们获取TransformableContainer。 我们从上下文中删除它并执行保存。

现在我们认为将更改为4并执行保存后,应该将4保存为该值。 显然不是这样。 当该值实际为3时,我们会感到无礼。在控制台中,我们将获得以下日志。

 值设为3 
值从3变为4
transformableContainer.transformableAttribute.value:3

在考虑使用可变形属性时,请记住上面注释如果将可变类型用作可转换属性,则将面临危险。

您可以通过为Transformable属性使用非可变类型来避免这种情况。 如果不完全替换对象,则无法更改该值。 如果替换了对象,CoreData会知道它已更改,并将拥有的托管对象标记为具有挂起的更改。 下次在上下文上调用保存时,它将被保存。 因此,基本上,我们如下更改UnpredicatbleValue的实现

现在我们受到了编译器的保护。 每当我们更改值时,都会抱怨无法更改值。 我们唯一的选择是使用具有新值集的较新对象替换较旧的对象。 因此,Core Data能够跟踪更改,因此我们可以避免之前遇到的危险。

希望这可以帮助。