Class

NSManagedObjectContext

An object representing a single object space or scratch pad that you use to fetch, create, and save managed objects.

Overview

A context consists of a group of related model objects that represent an internally consistent view of one or more persistent stores. Changes to managed objects are held in memory, in the associated context, until that context is saved to one or more persistent stores. A single managed object instance exists in one and only one context, but multiple copies of an object can exist in different contexts. Thus an object is unique to a particular context.

Life Cycle Management

The context is a powerful object with a central role in the life cycle of managed objects, with responsibilities from life cycle management (including faulting) to validation, inverse relationship handling, and undo/redo. Through a context you can retrieve or “fetch” objects from a persistent store, make changes to those objects, and then either discard the changes or—again through the context—commit them back to the persistent store. The context is responsible for watching for changes in its objects and maintains an undo manager so you can have finer-grained control over undo and redo. You can insert new objects and delete ones you have fetched, and commit these modifications to the persistent store.

All objects fetched from an external store are registered in a context together with a global identifier (an instance of NSManagedObjectID) that’s used to uniquely identify each object to the external store.

Parent Store

Managed object contexts have a parent store from which they retrieve data representing managed objects and through which they commit changes to managed objects.

Prior to OS X v10.7 and iOS v5.0, the parent store is always a persistent store coordinator. In macOS 10.7 and later and iOS v5.0 and later, the parent store may be another managed object context. Ultimately the root of a context’s ancestry must be a persistent store coordinator. The coordinator provides the managed object model and dispatches requests to the various persistent stores containing the data.

If a context’s parent store is another managed object context, fetch and save operations are mediated by the parent context instead of a coordinator. This pattern has a number of usage scenarios, including:

  • Performing background operations on a second thread or queue.

  • Managing discardable edits, such as in an inspector window or view.

As the first scenario implies, a parent context can service requests from children on different threads. You cannot, therefore, use parent contexts created with the thread confinement type (see Concurrency).

When you save changes in a context, the changes are only committed “one store up.” If you save a child context, changes are pushed to its parent. Changes are not saved to the persistent store until the root context is saved. (A root managed object context is one whose parent context is nil.) In addition, a parent does not pull changes from children before it saves. You must save a child context if you want ultimately to commit the changes.

Notifications

A context posts notifications at various points—see NSManagedObjectContextObjectsDidChange for example. Typically, you should register to receive these notifications only from known contexts:

[[NSNotificationCenter defaultCenter] addObserver:self
                                      selector:@selector(<#Selector name#>)
                                      name:NSManagedObjectContextDidSaveNotification
                                      object:<#A managed object context#>];

Several system frameworks use Core Data internally. If you register to receive these notifications from all contexts (by passing nil as the object parameter to a method such as addObserver(_:selector:name:object:)), then you may receive unexpected notifications that are difficult to handle.

Concurrency

Core Data uses thread (or serialized queue) confinement to protect managed objects and managed object contexts (see Core Data Programming Guide). A consequence of this is that a context assumes the default owner is the thread or queue that allocated it—this is determined by the thread that calls its init method. You should not, therefore, initialize a context on one thread then pass it to a different thread. Instead, you should pass a reference to a persistent store coordinator and have the receiving thread/queue create a new context derived from that. If you use Operation, you must create the context in main (for a serial queue) or start (for a concurrent queue).

When you create a context you specify the concurrency pattern with which you will use it using init(concurrencyType:). When you create a managed object context using init(concurrencyType:), you have two options for its thread (queue) association

  • Private queue (privateQueueConcurrencyType): The context creates and manages a private queue.

  • Main queue (mainQueueConcurrencyType): The context is associated with the main queue, and as such is tied into the application’s event loop, but it is otherwise similar to a private queue-based context. You use this queue type for contexts linked to controllers and UI objects that are required to be used only on the main thread.

You use contexts using the queue-based concurrency types in conjunction with perform(_:) and performAndWait(_:). You group “standard” messages to send to the context within a block to pass to one of these methods. There are two exceptions:

  • Setter methods on queue-based managed object contexts are thread-safe. You can invoke these methods directly on any thread.

  • If your code is executing on the main thread, you can invoke methods on the main queue style contexts directly instead of using the block based API.

perform(_:) and performAndWait(_:) ensure the block operations are executed on the queue specified for the context. The perform(_:) method returns immediately and the context executes the block methods on its own thread. With the performAndWait(_:) method, the context still executes the block methods on its own thread, but the method doesn’t return until the block is executed.

It’s important to appreciate that blocks are executed as a distinct body of work. As soon as your block ends, anyone else can enqueue another block, undo changes, reset the context, and so on. Thus blocks may be quite large, and typically end by invoking save().

var savedOK = falsemyMOC.performBlockAndWait() {
    //Do lots of things with the context.
    do {
        myMOC.save()
        savedOK = true
    } catch {        print("Error saving context: \(error)")
    }
}

You can also perform other operations, such as:

let fr = NSFetchRequest(entityName:"Entity")
var rCount = 0
 
context.performBlockAndWait() {
    rCount = context.countForFetchRequest(fr, error: &error)
    if rCount == NSNotFound {
        // Handle the error.
    }
}
print("Retrieved \(rCount) items")

Subclassing Notes

You are strongly discouraged from subclassing NSManagedObjectContext. The change tracking and undo management mechanisms are highly optimized and hence intricate and delicate. Interposing your own additional logic that might impact processPendingChanges() can have unforeseen consequences. In situations such as store migration, Core Data will create instances of NSManagedObjectContext for its own use. Under these circumstances, you cannot rely on any features of your custom subclass. Any NSManagedObject subclass must always be fully compatible with NSManagedObjectContext (that is, it cannot rely on features of a subclass of NSManagedObjectContext).

Topics

Configuring a Context

init(concurrencyType: NSManagedObjectContextConcurrencyType)

Initializes a context with a given concurrency type.

var persistentStoreCoordinator: NSPersistentStoreCoordinator?

The persistent store coordinator of the context.

var parent: NSManagedObjectContext?

The parent of the context.

var name: String?

The developer-provided name of the context.

var userInfo: NSMutableDictionary

The user information for the context.

init()Deprecated

Registering and Fetching Objects

func fetch(NSFetchRequest<NSFetchRequestResult>)

Returns an array of objects that meet the criteria specified by a given fetch request.

func count(for: NSFetchRequest<NSFetchRequestResult>)

Returns the number of objects a given fetch request would have returned if it had been passed to executeFetchRequest:error:.

func registeredObject(for: NSManagedObjectID)

Returns the object for a specified ID, if the object is registered with the context.

func object(with: NSManagedObjectID)

Returns an object for a specified ID even if the object needs to be fetched.

func existingObject(with: NSManagedObjectID)

Returns the object for the specified ID or nil if the object does not exist.

var registeredObjects: Set<NSManagedObject>

The set of objects registered with the context.

func count<T>(for: NSFetchRequest<T>)

Returns the number of objects a given fetch request would have returned.

func execute(NSPersistentStoreRequest)

Passes a request to the persistent store without affecting the contents of the managed object context and returns a persistent store result.

func fetch<T>(NSFetchRequest<T>)

Returns an array of objects that meet the criteria specified by a given fetch request.

func refreshAllObjects()

Refreshes all currently registered objects that are associated with this context.

var retainsRegisteredObjects: Bool

A Boolean value that indicates whether the context keeps strong references to all registered managed objects.

Managing Managed Objects

var shouldDeleteInaccessibleFaults: Bool

A Boolean value that indicates the behavior of inaccessible faults.

var insertedObjects: Set<NSManagedObject>

The set of objects that have been inserted into the context but not yet saved in a persistent store.

var updatedObjects: Set<NSManagedObject>

The set of objects registered with the context that have uncommitted changes.

var deletedObjects: Set<NSManagedObject>

The set of objects that will be removed from their persistent store during the next save operation.

func insert(NSManagedObject)

Registers an object to be inserted in the context’s persistent store the next time changes are saved.

func delete(NSManagedObject)

Specifies an object that should be removed from its persistent store when changes are committed.

func assign(Any, to: NSPersistentStore)

Specifies the store in which a newly inserted object will be saved.

func obtainPermanentIDs(for: [NSManagedObject])

Converts to permanent IDs the object IDs of the objects in a given array.

func detectConflicts(for: NSManagedObject)

Marks an object for conflict detection.

func refresh(NSManagedObject, mergeChanges: Bool)

Updates the persistent properties of a managed object to use the latest values from the persistent store.

func processPendingChanges()

Forces the context to process changes to the object graph.

func observeValue(forKeyPath: String?, of: Any?, change: [String : Any]?, context: UnsafeMutableRawPointer?)

Allows a context that has registered as an observer of a value to be notified of a change to that value.

Managing Concurrency

var automaticallyMergesChangesFromParent: Bool

A Boolean value that indicates whether the context automatically merges changes saved to its persistent store coordinator or parent context.

var queryGenerationToken: NSQueryGenerationToken?

Returns the token associated with the query generation currently in use by this context.

var mergePolicy: Any

The merge policy of the context.

var transactionAuthor: String?

The author for the context that is used as an identifier in persistent history transactions.

func mergeChanges(fromContextDidSave: Notification)

Merges the changes specified in a given notification.

func setQueryGenerationFrom(NSQueryGenerationToken?)

Sets the query generation this context should use.

enum NSManagedObjectContextConcurrencyType

Constants to indicate the concurrency pattern with which a context will be used.

let NSManagedObjectContextQueryGenerationKey: String

Constant used to reference the query generation token.

Managing Notifications

static let NSManagedObjectContextObjectsDidChange: NSNotification.Name

A notification of changes made to managed objects associated with this context.

static let NSManagedObjectContextDidSave: NSNotification.Name

A notification that the context completed a save.

static let NSManagedObjectContextWillSave: NSNotification.Name

A notification that the context is about to save.

let NSInsertedObjectsKey: String

A key for the set of objects that were inserted into the context.

let NSUpdatedObjectsKey: String

A key for the set of objects that were updated.

let NSDeletedObjectsKey: String

A key for the set of objects that were marked for deletion during the previous event.

let NSRefreshedObjectsKey: String

A key for the set of objects that were refreshed but were not dirtied in the scope of this context.

let NSInvalidatedObjectsKey: String

A key for the set of objects that were invalidated.

let NSInvalidatedAllObjectsKey: String

A key that specifies that all objects in the context have been invalidated.

Managing Unsaved and Uncommitted Changes

func save()

Attempts to commit unsaved changes to registered objects to the context’s parent store.

var hasChanges: Bool

A Boolean value that indicates whether the context has uncommitted changes.

Undoing Changes

var undoManager: UndoManager?

The undo manager of the context.

func undo()

Sends an undo message to the context’s undo manager, asking it to reverse the latest uncommitted changes applied to objects in the object graph.

func redo()

Sends an redo message to the context’s undo manager, asking it to reverse the latest undo operation applied to objects in the object graph.

func reset()

Returns the context to its base state.

func rollback()

Removes everything from the undo stack, discards all insertions and deletions, and restores updated objects to their last committed values.

Handling Delete Propagation

var propagatesDeletesAtEndOfEvent: Bool

A Boolean value that indicates whether the context propagates deletes at the end of the event in which a change was made.

Managing the Staleness Interval

var stalenessInterval: TimeInterval

The maximum length of time that may have elapsed since the store previously fetched data before fulfilling a fault issues a new fetch.

Performing Block Operations

func perform(() -> Void)

Asynchronously performs a given block on the context’s queue.

func performAndWait(() -> Void)

Synchronously performs a given block on the context’s queue.

Core Data Versions

var NSCoreDataVersionNumber: Double

The version of Core Data available in the current process.

var NSCoreDataVersionNumber10_10: Double

The Core Data version number released with macOS 10.10.

var NSCoreDataVersionNumber10_10_2: Double

The Core Data version number released with macOS 10.10.2.

var NSCoreDataVersionNumber10_10_3: Double

The Core Data version number released with macOS 10.10.3.

var NSCoreDataVersionNumber10_11: Double

The Core Data version number released with macOS 10.11.

var NSCoreDataVersionNumber10_11_3: Double

The Core Data version number released with macOS 10.11.3.

var NSCoreDataVersionNumber10_4: Double

The Core Data version number released with macOS 10.4.

var NSCoreDataVersionNumber10_4_3: Double

The Core Data version number released with macOS 10.4.3.

var NSCoreDataVersionNumber10_5: Double

The Core Data version number released with macOS 10.5.

var NSCoreDataVersionNumber10_5_3: Double

The Core Data version number released with macOS 10.5.3.

var NSCoreDataVersionNumber10_6: Double

The Core Data version number released with macOS 10.6.

var NSCoreDataVersionNumber10_6_2: Double

The Core Data version number released with macOS 10.6.2.

var NSCoreDataVersionNumber10_6_3: Double

The Core Data version number released with macOS 10.6.3.

var NSCoreDataVersionNumber10_7: Double

The Core Data version number released with macOS 10.7.

var NSCoreDataVersionNumber10_7_2: Double

The Core Data version number released with macOS 10.7.2.

var NSCoreDataVersionNumber10_7_3: Double

The Core Data version number released with macOS 10.7.3.

var NSCoreDataVersionNumber10_7_4: Double

The Core Data version number released with macOS 10.7.4.

var NSCoreDataVersionNumber10_8: Double

The Core Data version number released with macOS 10.8.

var NSCoreDataVersionNumber10_8_2: Double

The Core Data version number released with macOS 10.8.2.

var NSCoreDataVersionNumber10_9: Double

The Core Data version number released with macOS 10.9.

var NSCoreDataVersionNumber10_9_2: Double

The Core Data version number released with macOS 10.9.2.

var NSCoreDataVersionNumber10_9_3: Double

The Core Data version number released with macOS 10.9.3.

var NSCoreDataVersionNumber_iPhoneOS_3_0: Double

The Core Data version number released with iOS 3.

var NSCoreDataVersionNumber_iPhoneOS_3_1: Double

The Core Data version number released with iOS 3.1.

var NSCoreDataVersionNumber_iPhoneOS_3_2: Double

The Core Data version number released with iOS 3.2.

var NSCoreDataVersionNumber_iPhoneOS_4_0: Double

The Core Data version number released with iOS 4.

var NSCoreDataVersionNumber_iPhoneOS_4_1: Double

The Core Data version number released with iOS 4.1.

var NSCoreDataVersionNumber_iPhoneOS_4_2: Double

The Core Data version number released with iOS 4.2.

var NSCoreDataVersionNumber_iPhoneOS_4_3: Double

The Core Data version number released with iOS 4.2.

var NSCoreDataVersionNumber_iPhoneOS_5_0: Double

The Core Data version number released with iOS 5.

var NSCoreDataVersionNumber_iPhoneOS_5_1: Double

The Core Data version number released with iOS 5.1.

var NSCoreDataVersionNumber_iPhoneOS_6_0: Double

The Core Data version number released with iOS 6.

var NSCoreDataVersionNumber_iPhoneOS_6_1: Double

The Core Data version number released with iOS 6.1.

var NSCoreDataVersionNumber_iPhoneOS_7_0: Double

The Core Data version number released with iOS 7.0.

var NSCoreDataVersionNumber_iPhoneOS_7_1: Double

The Core Data version number released with iOS 7.1.

var NSCoreDataVersionNumber_iPhoneOS_8_0: Double

The Core Data version number released with iOS 8.0.

var NSCoreDataVersionNumber_iPhoneOS_8_3: Double

The Core Data version number released with iOS 8.3.

var NSCoreDataVersionNumber_iPhoneOS_9_0: Double

The Core Data version number released with iOS 9.0.

var NSCoreDataVersionNumber_iPhoneOS_9_2: Double

The Core Data version number released with iOS 9.2.

var NSCoreDataVersionNumber_iPhoneOS_9_3: Double

The Core Data version number released with iOS 9.3.

Errors

let NSAffectedObjectsErrorKey: String

The key for objects prompting an error.

let NSAffectedStoresErrorKey: String

The key for stores prompting an error.

let NSDetailedErrorsKey: String

If multiple validation errors occur in one operation, they are collected in an array and added with this key to the “top-level error” of the operation.

let NSSQLiteErrorDomain: String

Domain for SQLite errors.

Deprecated

func lock()

Attempts to acquire a lock on the context.

Deprecated
func unlock()

Relinquishes a previously acquired lock.

Deprecated
func tryLock()

Attempts to acquire a lock.

Deprecated

Relationships

Inherits From

See Also

Core Data Stack

class NSPersistentContainer

A container that encapsulates the Core Data stack in your application.

class NSPersistentStoreCoordinator

A coordinator that associates persistent stores with a model (or a configuration of a model) and that mediates between the persistent stores and the managed object contexts.

class NSManagedObjectModel

An object that describes a schema—a collection of entities (data models) that you use in your application.