无论应用程序使用哪种持久性框架,开发人员都将决定存储在应用程序的持久性存储中的内容。 这也意味着在将数据插入持久存储之前,开发人员负责验证数据。
如果您的应用程序使用Core Data保留数据,那么您很幸运。 该框架具有许多用于在将对象持久化到磁盘之前对其进行验证的API。 在本教程中,我将向您展示Core Data为开发人员提供了哪些用于验证对象的选项。
1.项目设置
最好的学习方法就是做事。 打开Xcode并基于Single View Application模板创建一个新项目。
将项目命名为Validation并将Language设置为Swift 。 选中底部的使用核心数据 ,然后单击下一步 。
2.填充数据模型
打开Validation.xcdatamodeld ,创建一个新实体,并将其命名为User。 将以下属性添加到用户实体:
- 字符串类型的第一个
- 字符串类型的最后一个
- 字符串类型的电子邮件
- 整数类型的年龄 16
创建另一个实体,将其命名为Note ,并将以下属性添加到该实体:
- 字符串类型的标题
- 字符串类型的内容
- Date类型的createdAt
一个用户可以有多个注释,而一个注释只能属于一个用户。 这意味着我们需要以Note实体为目标,向User实体添加To To关系。 我们还需要将一个“一对一”关系添加到“ 注释”实体,并以“ 用户”实体为目标,并以“ 注释”为逆向关系。 这就是Xcode数据模型编辑器中的样子。
3.约束属性
可以在数据模型中定义公共约束。 让我告诉你这是如何工作的。 打开Validation.xcdatamodeld并选择用户实体。 选择电子邮件属性,然后打开右侧的数据模型检查器 。
在“ 验证”部分,您可以设置属性的最小和最大长度。 您甚至可以输入一个正则表达式,该属性的值必须匹配才能有效。 数据模型检查器还添加了设置默认值的功能,这对于必需的属性很方便。
这给我们带来了对属性的最明显的约束,即它们的可选性。 通过取消选中顶部的Optional复选框,您可以告诉Core Data该属性必须具有一个值才能使其有效。
如果对象未通过验证,则在执行保存操作时,Core Data会引发错误。 毋庸置疑,Core Data不允许将无效对象推送到应用程序的持久性存储中。
如果您选择User实体的age属性,您会注意到Validation部分看起来略有不同。 由于age属性的类型为Integer 16 ,因此可以为该属性设置最小值和最大值。 您也可以定义默认值。
选择Note实体的createdAt属性,然后打开Data Model Inspector 。 请注意,您可以指定最小和最大日期以及默认日期。
数据模型中定义的约束最重要的缺点是缺乏动态性。 例如,如果要将Date类型的属性约束为基于当前日期的值,则需要在代码中实现自定义验证。 我们稍后看一下它是如何工作的。
4.约束关系
关系与属性没有很大的不同。 它们也可能受到约束。 关系可以是可选的,也可以是必需的。 一对多关系的计数可以限制为最小值和最大值。 选择用户实体的notes属性,然后打开“ 数据模型检查器” 。 音符关系的计数可以具有最小值和最大值。
能够向数据模型添加约束是一个强大的概念,很高兴知道它已内置在Core Data框架中。
5.验证对象
通过取消选中“ 数据模型检查器”中的“ 可选”复选框,选择“ 用户”实体并标记所需的每个属性。 选择age属性,并将最小值设置为0并将最大值设置为120 。 将属性的默认值设置为21 。
打开AppDelegate.swift并更新application(_:didFinishLaunchingWithOptions:)
,如下所示。 我们创建User实体的实例并填充其属性。 请注意,我们将age属性设置为一个超出数据模型中指定的最大值的值。 我们可以通过调用validateForInsert()
来询问托管对象对于插入持久存储是否有效。 由于此方法正在抛出,因此将其包装在do-catch
语句中。
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
if let entity = NSEntityDescription.entityForName("User", inManagedObjectContext: self.managedObjectContext) {
// Create Managed Object
let user = NSManagedObject(entity: entity, insertIntoManagedObjectContext: self.managedObjectContext)
// Populate Managed Object
user.setValue(140, forKey: "age")
user.setValue("Bart", forKey: "first")
user.setValue("Jacobs", forKey: "last")
user.setValue("me@icloud.com", forKey: "email")
do {
try user.validateForInsert()
} catch {
let validationError = error as NSError
print(validationError)
}
}
return true
}
如果您在模拟器或物理设备上运行该应用程序,则应该在控制台中看到以下错误。
Error Domain=NSCocoaErrorDomain Code=1610 "The operation couldn’t be completed. (Cocoa error 1610.)" UserInfo={NSValidationErrorObject=<NSManagedObject: 0x7fef63611dd0> (entity: User; id: 0x7fef63613eb0 <x-coredata:///User/t8C45E95D-D8C3-4900-82FA-BC313D53D5882> ; data: {
age = 140;
email = "me@icloud.com";
first = Bart;
last = Jacobs;
notes = (
);
}), NSValidationErrorValue=140, NSValidationErrorKey=age, NSLocalizedDescription=The operation couldn’t be completed. (Cocoa error 1610.)}
该错误非常清楚托管对象存在什么问题。 即使本地化描述有点模糊,错误也表明age属性的值不符合我们在数据模型中定义的约束。
验证期间可能会引发多个验证错误。 让我向您展示一下。 为避免迁移问题,请从模拟器中删除该应用程序。 重新访问数据模型并选择用户实体的最后一个属性。 打开右侧的数据模型检查器 ,然后取消选中“ 可选”以使该属性成为必需属性。
打开AppDelegate.swift并删除设置用户记录的姓氏的行。
user.setValue("Jacobs", forKey: "last")
再次运行该应用程序,然后检查以在控制台中输出。
Error Domain=NSCocoaErrorDomain Code=1560 "(null)" UserInfo={NSDetailedErrors=(
"Error Domain=NSCocoaErrorDomain Code=1610 \"The operation couldn\U2019t be completed. (Cocoa error 1610.)\" UserInfo={NSValidationErrorObject=<NSManagedObject: 0x7feab8419690> (entity: User; id: 0x7feab84196f0 <x-coredata:///User/tD1D0A3BA-7F23-41A7-9567-5C1A30D6A0132> ; data: {\n age = 140;\n email = \"me@icloud.com\";\n first = Bart;\n last = nil;\n notes = (\n );\n}), NSValidationErrorValue=140, NSValidationErrorKey=age, NSLocalizedDescription=The operation couldn\U2019t be completed. (Cocoa error 1610.)}",
"Error Domain=NSCocoaErrorDomain Code=1570 \"The operation couldn\U2019t be completed. (Cocoa error 1570.)\" UserInfo={NSValidationErrorKey=last, NSLocalizedDescription=The operation couldn\U2019t be completed. (Cocoa error 1570.), NSValidationErrorObject=<NSManagedObject: 0x7feab8419690> (entity: User; id: 0x7feab84196f0 <x-coredata:///User/tD1D0A3BA-7F23-41A7-9567-5C1A30D6A0132> ; data: {\n age = 140;\n email = \"me@icloud.com\";\n first = Bart;\n last = nil;\n notes = (\n );\n})}"
)}
错误对象的userInfo
词典包含一个错误数组,这些错误通知我们在验证过程中出了什么问题。 请理解,如果您尝试保存未通过验证的托管对象,则会引发相同的错误。
结论
数据验证是数据持久性的关键方面。 您需要确保插入持久存储中的数据有效。 换句话说,您插入的数据需要符合您在数据模型和应用程序代码中定义的要求。
下周,我将向您展示如何在代码中创建更复杂的验证规则。 即使这种方法需要更多的工作,代码中的验证规则也更加灵活和强大。
翻译自: https://code.tutsplus.com/tutorials/data-validation-with-core-data-common-constraints--cms-26621