掌握CoreData(第8部分:验证核心数据)

核心数据 ,使您可以将验证逻辑放入托管对象模型中并指定最常见的约束,而不是在代码中编写验证逻辑。 将数据转储到持久性存储之前 ,您可以对对象应用验证。 如果对象遵循约束,则上下文数据将成功持久保存,否则它将引发错误。 添加约束是开发人员的责任。 该框架具有许多用于在将对象持久化到磁盘之前对其进行验证的API。 在本教程中,我将向您展示Core Data为开发人员提供的验证对象的选项。 在第2部分中,我们写了这一点

托管对象上下文(MOC)

它提供缓存,更改跟踪,延迟加载,重做,撤消和验证功能

验证在核心数据中如何工作

验证约束仅在保存操作期间或在请求时由Core Data应用 (您可以在对您的应用程序流程有意义的任何时候直接调用验证方法)

入门

您可以在此处下载启动程序项目。 该项目是教程的继续,请参见第5部分和第7部分,我们在其中创建了该项目。

如果您遵循以前的教程,请先删除该应用程序,然后再开始执行任何操作

属性验证

转到CrudOperationCoreData.xcdatamodeld→点击用户实体→双击firstName属性→在右侧的模型检查器中添加验证。 我们添加了firstName的两个验证最小最大长度,还添加了默认值,如图1所示。确保选中了最大和最小长度复选框。

让我们深入研究代码并检查验证是否有效。 如您所见,当我们创建用户实体时, 默认值被分配给firstName属性,并且当我们使用12个以上的字符更新firstName值时,它在内存中的上下文中成功更新,但是当我们尝试将更改提交到持久性存储时,它将检查首先进行验证,如果验证失败,则会抛出错误,如图2所示

您可以在对实体本身调用save方法throw validateForInsert()validateForUpdate()实例方法之前请求验证,并且可以覆盖此方法以对代码应用自定义验证。
我们将在本部分的最后一部分中查看自定义验证

日期验证

您可以在Date上应用最小和最大验证,如图3所示。
确保应选中“最小和最大日期”复选框,否则验证将不起作用。

关系验证

关系与属性没有很大的不同。 它们也可能受到约束。 关系可以是可选的,也可以是必需的。 一对多关系的计数可以限制为最小值最大值

转到CrudOperationCoreData.xcdatamodeld →在用户实体上点击→在任务关系属性上点击→在​​模型检查器中,添加最小最大验证,如图4所示。

首先删除该应用程序,并在User对象上添加三个 任务 ,如图5所示。

当我们尝试保存它时。 因为我们为单个User对象限制(两个)添加了max task对象,所以我们将添加三个,这将引发如图6所示的错误。 它在内存中的上下文上成功添加了三个任务,但是当我们尝试将更改(使用save()方法)提交给持久性存储时,它将首先检查验证,如果验证失败,则会抛出错误,如图6所示

您可以在对实体本身调用save方法throw validateForInsert()validateForUpdate()实例方法之前请求验证,并且可以覆盖此方法以对代码应用自定义验证。
我们将在本部分的最后一部分中查看自定义验证

正则表达式验证

现在,我们将探讨如何在模型检查器核心数据中添加正则表达式。 我们将对用户的firstName属性应用正则表达式,该属性将允许至少一个字符,并且该字符将为小写^ [az] {1,} $)字母,如图7所示。

当我们尝试使用大写字母保存对象时,它将抛出错误,如图8所示。

自定义属性级别验证

NSManagedObject为实现属性(和属性)值提供了一致的钩子。 因此,在本节中,我们将首先进行比理论编码的部分,因为它的理论很复杂。 在上一节中,我们使用托管对象模型检查器功能应用了约束。

使用代码应用约束

在此编码部分中,我们将使用代码应用最小最大长度约束。 首先删除应用程序,并从核心数据模型文件中删除上一节中应用的较旧约束。

从Xcode的File菜单中选择New→File… ,然后选择Swift文件→“ User + CoreDataValidations”→创建

对于自定义验证,我们需要重写 validateValue方法。 输入值是指向对象引用(ID *)的指针。 这意味着原则上您可以更改输入值。 但是,强烈建议不要这样做,因为内存管理可能存在严重的问题。

这与以前的swift版本不同,因此对于较旧的项目可能不起作用,请参阅相关文档 。 如您在图9中所看到的,它正在检查用户secondName属性,如果它为nil ,为或超过12个字符的限制,它将抛出错误

现在添加具有secondName属性的User ,其最大数量限制为12,并查看它是否显示了自定义错误,以及我们刚刚创建的错误,如您在图10中所看到的,它显示了自定义错误“ User Second name不能大于12个字符” 。

实施自定义属性间验证

一个对象的所有单个属性的值都可能是有效的,而组合却是无效的 。 例如,如果用户firstNamesecondName都不应超过12个字符的限制, 则将对象插入或保存到持久性存储中

NSManagedObject通过validateFor…等方法(如validateForUpdate :)为验证提供了额外的机会-更新,插入和删除 如果您实现自定义的属性间验证方法,则首先调用超类的实现,以确保还调用了各个属性验证方法。 如果超类的实现失败(即,如果存在无效的属性值),则可以执行以下操作之一:

  • 返回NO和由超类的实现创建的错误。
  • 继续执行验证,查找值的不一致组合。

正如您在图11和12中看到的,我们没有做任何事情

  1. User secondName属性上,我们添加少于12个字符的值
  2. firstName属性上,我们超过了12个字符的限制
  3. 当我们调用save()方法时,它首先为每个属性自定义验证调用validatevalue ,因为我们仅提供secondName属性,它将验证secondName并将其传递。
  4. 在重写该方法之后, validateForInsert()将调用以检查属性间验证,并且由于firstName与验证不匹配,它将抛出我们刚刚创建的自定义错误。

摘要

在第8部分中,我们研究了如何使用核心数据功能来验证对象。 我们首先查看了构建验证,然后还查看了一些自定义验证。

接下来是什么?

在下一部分中,我们将通过编码和图表深入了解NSFetchRequest。

有用的链接

https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreData/ObjectValidation.html

https://code.tutsplus.com/tutorials/data-validation-with-core-data-common-constraints–cms-26621

https://code.tutsplus.com/tutorials/data-validation-with-core-data-advanced-constraints–cms-26623