Core Data Reference
Kip Landergren
(Updated: )
Contents
- Terminology
- Class and Protocol Overview
- Creating an Object Model
- Working with Stores
- Working with Data
- Working with Managed Objects
- Best Practices
- Format Strings
- Resources
Terminology
stack | the core data classes necessary to manage and persist your application’s data layer |
container | unified interface for creation, management, and access of a single core data stack |
object model / model | the structure of your object graph data |
context | work area for interacting with objects |
coordinator | traffic cop between contexts, stores, and models |
store / persistent store | maintainer of data (when persistent, on disk) over time |
managed object | a realized instance of an entity defined by your model, specific to a context |
entity | data structure of an object within the object graph. AKA a database table |
attribute | a named property with an associated value |
relationship | a named property with an associated object (or objects) |
fetch | to retrieve data from a persistent store |
fetch request | search criteria for a query to a persistent store |
fetched results controller | executes a fetch request and manages results |
fault | placeholder object in the persistent store; a promise of a future object |
fire a fault / faulted / faulting | realizing an object into memory, typically when the instance variable of a fault is accessed; should be transparent |
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 valuesNSRelationshipDescription
, for associated relationships
Note: 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.
Important note: 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
propertytitle
generated by Xcode will be aString?
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
Note: 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
andreturnsDistinctResults
- subquery type expressions in an
NSExpressionDescription
do not appear to be evaluated correctly, the sameSUBQUERY(...)
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 anNSFetchRequest
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 theNSFetchedResultsController
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 toreset()
- 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. usenewIndexPath
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
hasNSManagedObject
subclass namedBarMO
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 thanrollback()
- 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 returningnil
if it does not exist. note: I do not know why the signature is notNSManagedObject?
- 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 returntrue
Best Practices
- exercise Core Data in tests
- consolidate and centralize definition of
NSFetchRequest
andNSPredicate
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