If your application uses Core Data for persisting data, then you are in luck. The framework has a number of APIs for validating objects before they are persisted to disk. In this tutorial, I show you what options Core Data offers developers for validating objects.
1. Project Setup
The best way to learn is by doing. Open Xcode and create a new project based on the Single View Application template.
![]() |
![]() |
Open Validation.xcdatamodeld, create a new entity, and name it User. Add the following attributes to the User entity:
- first of type String
- last of type String
- email of type String
- age of type Integer 16
- title of type String
- contents of type String
- createdAt of type Date
![]() |
![]() |
Common constraints can be defined in the data model. Let me show you how this works. Open Validation.xcdatamodeld and select the User entity. Select the email attribute and open the Data Model Inspector on the right.
![]() |
This brings us to the most obvious constraint for attributes, their optionality. By unchecking the Optional checkbox at the top, you tell Core Data that the attribute must have a value for it to be valid.
If an object doesn't pass validation, Core Data throws an error if a save operation is performed. It goes without saying that Core Data doesn't allow invalid objects to be pushed to the application's persistent store.
If you select the age attribute of the User entity, you will notice that the Validation section looks slightly different. Because the age attribute is of type Integer 16, you can set a minimum and a maximum value for the attribute. You can also define a default value.
![]() |
![]() |
4. Constraining Relationships
Relationships are not very different from attributes. They too can be constrained. A relationship can be optional or required. The count of a To Many relationship can be constrained to a minimum and a maximum value. Select the notes attribute of the User entity and open the Data Model Inspector. The count of the notes relationship can have a minimum and a maximum value.
![]() |
Having the ability to add constraints to a data model is a powerful concept and it is nice to know that this is built into the Core Data framework.
5. Validating Objects
Select the User entity and mark every attribute as required by unchecking the Optional checkbox in the Data Model Inspector. Select the age attribute and set the minimum value to 0 and the maximum value to 120. Set the attribute's default value to 21.
![]() |
Open AppDelegate.swift and update application(_:didFinishLaunchingWithOptions:) as shown below. We create an instance of the User entity and populate its attributes. Note that we set the age attribute to a value that exceeds the maximum value we specified in the data model. We can ask the managed object whether it is valid for insertion into the persistent store by invoking validateForInsert(). Because this method is throwing, we wrap it in a do-catch statement.
- 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
- }
If you run the application in the simulator or on a physical device, you should see the following error in the console.
- 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.)}
The error is pretty clear about what is wrong with the managed object. Even though the localized description is a bit vague, the error indicates the value of the age attribute isn't meeting the constraints we defined in the data model.
It is possible that multiple validation errors were thrown during validation. Let me show you what that looks like. To avoid migration issue, delete the application from simulator. Revisit the data model and select the last attribute of the User entity. Open the Data Model Inspector on the right and uncheck Optional to make the attribute required.
Open AppDelegate.swift and remove the line in which we set the last name of the User record.
- user.setValue("Jacobs", forKey: "last")
Run the application again and inspect to output in the console.
- 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})}"
- )}
The userInfo dictionary of the error object contains an array of errors that inform us what went wrong during validation. Understand that the same errors are thrown if you try to save a managed object that doesn't pass validation.
Conclusion
Data validation is a key aspect of data persistence. You need to make sure that the data you insert into the persistent store is valid. In other words, the data you insert needs to conform to the requirements you define in the data model and your application code.
Written by Bart Jacobs
If you found this post interesting, follow and support us.
Suggest for you:









No comments:
Post a Comment