Core Data Reference
Kip Landergren
(Updated: )
Contents
- Class and Protocol Overview
- Creating an Object Model
- Working with Stores
- Working with Data
- Working with Managed Objects
- Best Practices
- Format Strings
- Resources
- Terminology
Class and Protocol Overview
Core Data Stack
NSPersistentContainer
Holds all Core Data stack objects. Provides convenient access to viewContext and the ability to create new background contexts / do background work.
Should be subclassed—even if just an empty class—to better find the NSManagedObjectModel describing your object graph.
NSPersistentContainer - Core Data | Apple Developer Documentation
NSManagedObjectModel
Describes the structure of your object graph data in a way that is understood by an NSPersistentStore. Managed via Xcode’s data modeling tool and stored on disk in your .xcdatamodeld file.
NSManagedObjectModel - Core Data | Apple Developer Documentation
NSManagedObjectContext
Intelligent scratch pad for access and management of NSManagedObject instances. Keeps changes in memory until saved to an NSPersistentStore. Objects must be saved for persistence to work.
NSManagedObjectContext - Core Data | Apple Developer Documentation
NSPersistentStoreCoordinator
Mediates and facilitates the communication between NSManagedObjectContext instances and NSPersistentStore instances by controlling management of the NSManagedObjectModel.
A coordinator is able to compare the app’s managed object model with the store’s version and automatically migrate it forward.
NSPersistentStoreCoordinator - Core Data | Apple Developer Documentation
NSPersistentStore
Abstract base class that maintains data over time. Concrete types include:
- SQLite (default on iOS)
- in-memory (no on-disk storage)
- binary
- XML (unavailable on iOS)
NSPersistentStore - Core Data | Apple Developer Documentation
Core Data Model
NSManagedObject
Container object for a realized NSEntityDescription, associated with a single NSManagedObjectContext.
NSManagedObject - Core Data | Apple Developer Documentation
NSEntityDescription
Describes the metadata of an entity managed by Core Data. Can be thought of like a data base table.
NSEntityDescription - Core Data | Apple Developer Documentation
NSPropertyDescription
Describes a single property of an entity managed by Core Data. Subclasses include:
- NSAttributeDescription, for associated values
- NSRelationshipDescription, for associated relationships
Special care should be taken to not choose names that overlap with existing no-parameter methods. The class documentation gives a good explanation of this.
NSPropertyDescription - Core Data | Apple Developer Documentation
Core Data Querying
NSFetchRequest
Describes the search criteria for retrieving data from a persistent store.
NSFetchRequest - Core Data | Apple Developer Documentation
NSFetchedResultsController
Manages the results of an NSFetchRequest and provides convenient functionality for integrating with UITableViewDataSource and UITableViewDelegate.
NSFetchedResultsController - Core Data | Apple Developer Documentation
NSFetchedResultsControllerDelegate
Protocol for communicating data changes encountered by the associated NSFetchedResultsController.
NSFetchedResultsControllerDelegate - Core Data | Apple Developer Documentation
Core Data Batch Operations
NSBatchDeleteRequest
Core Data typically loads data into memory to perform operations on it. This object will execute a delete request directly on the store, bypassing normal channels and the need to load data into memory.
Active contexts are not automatically made aware of a batch delete request—take special care to review that everything works as expected!
NSBatchDeleteRequest - Core Data | Apple Developer Documentation
Creating an Object Model
Important notes:
- set the correct value of Optional appropriate for your object graph, and any appropriate minimum or maximum number of objects
- marking a property Optional is not the same as Swift’s optional. Example: a non-optional String property title generated by Xcode will be a String? in the managed object. The optionality property will be used to ensure object graph consistency on context save. Note: marking a field or relationship as Optional may be better addressed by setting a default value—there is some subtlety with how SQLite handles NULL records to consider.
- there are protected property names, like description, and more information is described in the NSPropertyDescription documentation
- choosing the correct attribute type can be confusing; review the NSAttributeType documentation
CodeGen
Three options:
- Manual
- Class
- Extension
When you select extension you are responsible for creating the managed object subclass. Refer to the generated class to see the structure needed.
@NSManaged
Attribute that tells the swift compiler that Core Data will provide storage and declaration at run time.
Working with Stores
Deleting a store does not notify NSFetchedResultsViewController instances.
NSPersistentContainer will create Library/Application Support for you and initiatlize your .sqlite store there. Unknown at the moment if it is configurable, but I suspect it is.
Working with Data
Remember: a context always has an internally consistent object graph, but that does not mean it necessarily agrees with the persistent store on disk. Multiple contexts can exist, leading to conflict between what is “truth”. Review merge policy and locking for more info.
NSExpression
Important:
- aggregate expressions are not supported
- block-based expressions are not supported
- returning unique and distinct values is better handled by propertiesToGroupBy and returnsDistinctResults
- subquery type expressions in an NSExpressionDescription do not appear to be evaluated correctly, the same SUBQUERY(...) as a predicate works fine
- generally, expressions work best when constrained to performing simple calculations on a single entity’s data
NSExpressionDescription
Combine an expression, name, and result type to generate a virtual property in propertiesToFetch.
Note:
- needs to be used with .dictionaryResultType
- any filtering, like via a subquery, should go in the predicate
- multiple NSExpressionDescription objects can be added to an NSFetchRequest
NSPredicate
Generally: put the most restrictive predicate first for better performance.
// fetch a specific relationship with NSPredicate
let predicate = NSPredicate(format: "foo == %@", foo.objectID)
NSFetchRequest
Consider:
- setting fetchLimit
- setting fetchBatchSize
- an NSFetchRequest always hits the persistent store
- creating fetch requests in the managed object model
- sort descriptors and sections must match
NSFetchedResultsController
Tips
- create a transient relationship within your model to emulate a second order relationship. this will allow the NSFetchedResultsController to detect changes
Gotchas
- calling reset() on context does not fire events to delete. See more at this stackoverflow question.
- calling reset() invalidates any managed obejcts created or fetched before the call to reset()
- disallowed: custom comparator blocks in NSSortDescriptor
- disallowed: sorting on a computed property
NSFetchedResultsControllerDelegate
Tips
Prevent NSInternalInconsistencyException by not relying solely on controllerDidChangeContent.
Instead make use of:
- controllerWillChangeContent
- controller(_:didChange:at:for:newIndexPath:)
- controllerDidChangeContent
Gotchas
controller(_:didChange:at:for:newIndexPath:) has special rules based on the NSFetchedResultsChangeType :
- for .insert, indexPath is nil, despite what the debugger may say. use newIndexPath
Working with Managed Objects
Important
- do not override description
- a context will only have a single managed object per entry in a persistent store. the entry in a persistent store may be accessed by many contexts.
Conventions
- Subclass ends in “MO”, standing for “Managed Object”. e.g. entity Bar has NSManagedObject subclass named BarMO
Init
// creating a managed object
let bar = BarMO(context: context)
Accessing Properties
Generalized approach:
- create property accessors of the specific type / optionality you want to work with
NSManagedObjectContext
- consider setting name to disambiguate multiple contexts while debugging
- reset() is different than rollback()
- a child context is created by setting the parentContext property
- use existingObject(with:) when you want an object—not a fault—and can handle it returning nil if it does not exist. note: I do not know why the signature is not NSManagedObject?
- use object(with:) when you know the object exists and want to work with a fault
- creating and then deleting a managed object still leaves a trail within the context; e.g. hasChanges will return true
Best Practices
- exercise Core Data in tests
- consolidate and centralize definition of NSFetchRequest and NSPredicate instances
Format Strings
| %d | signed 32-bit integer |
| %@ | object |
More info in this Stack Overflow question: “What are the supported Swift String format specifiers?”.
Resources
Documentation
- Core Data | Apple Developer Documentation
- Core Data Model | Apple Developer Documentation
- Core Data Stack | Apple Developer Documentation
- Core Data Programming Guide - Documentation Archive
WWDC Talks
- WWDC 2016 Session 242 What’s New in Core Data
- WWDC 2017 Session 210 What’s New in Core Data
- WWDC 2018 Session 224 Core Data Best Practices
Terminology
- attribute
- 1.
A named property with an associated value.
Related:
- container
- 1.
Unified interface for creation, management, and access of a single core data stack.
Related:
- context
- 1.
Work area for interacting with objects.
Related:
- coordinator
- 1.
Traffic cop between contexts, stores, and models.
Related:
- entity
- 1.
Data structure of an object within the object graph. AKA a database table.
Related:
- fault
- 1.
Placeholder object in the persistent store; a promise of a future object.
Related:
- fetch
- 1.
To retrieve data from a persistent store.
Related:
- fetch request
- 1.
Search criteria for a query to a persistent store.
Related:
- fetched results controller
- 1.
Executes a fetch request and manages results.
Related:
- fire a fault
- 1.
Realizing an object into memory, typically when the instance variable of a fault is accessed; should be transparent.
Also: faulted, faulting
Related:
- managed object
- 1.
A realized instance of an entity defined by your model, specific to a context.
Related:
- object model (model)
- 1.
The structure of your object graph data.
Related:
- relationship
- 1.
A named property with an associated object (or objects).
Related:
- stack
- 1.
The core data classes necessary to manage and persist your application’s data layer.
Related:
- store (persistent store)
- 1.
Maintainer of data (when persistent, on disk) over time.
Related: