Questions tagged [nsmanagedobjectcontext]

An instance of NSManagedObjectContext represents a single “object space”. Its primary responsibility is to manage a collection of managed objects. These objects form a group of related model objects that represent an internally consistent view of 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. Available in iOS 3.0 and later in CoreData.

An instance of NSManagedObjectContext represents a single “object space” or scratch pad in an application. Its primary responsibility is to manage a collection of managed objects. These objects form a group of related model objects that represent an internally consistent view of 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 object uniquing is scoped 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 OS X v10.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 NSManagedObjectContextObjectsDidChangeNotification 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 Concurrency with Core Data). 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 NSOperation, you must create the context in main (for a serial queue) or start (for a concurrent queue).

In OS X v10.7 and later and iOS v5.0 and later, when you create a context you can specify the concurrency pattern with which you will use it using initWithConcurrencyType:. When you create a managed object context using initWithConcurrencyType:, you have three options for its thread (queue) association

Confinement (NSConfinementConcurrencyType)

For backwards compatibility, this is the default. You promise that context will not be used by any thread other than the one on which you created it. In general, to make the behavior explicit you’re encouraged to use one of the other types instead.

You can only use this concurrency type if the managed object context’s parent store is a persistent store coordinator.

Private queue (NSPrivateQueueConcurrencyType)

The context creates and manages a private queue.

Main queue (NSMainQueueConcurrencyType)

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.

If you use contexts using the confinement pattern, you send the contexts messages directly; it’s up to you to ensure that you send the messages from the right queue.

You use contexts using the queue-based concurrency types in conjunction with performBlock: and performBlockAndWait:. 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.

performBlock: and performBlockAndWait: ensure the block operations are executed on the queue specified for the context. The performBlock: method returns immediately and the context executes the block methods on its own thread. With the performBlockAndWait: 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:.

__block NSError *error;
__block BOOL savedOK = NO;
[myMOC performBlockAndWait:^{
    // Do lots of things with the context.
    savedOK = [myMOC save:&error];
}];

You can also perform other operations, such as:

NSFetchRequest *fr = [NSFetchRequest fetchRequestWithEntityName:@"Entity"];
__block NSUInteger rCount = 0;

[context performBlockAndWait:^() {
    NSError *error;
    rCount = [context countForFetchRequest:fr error:&error];
    if (rCount == NSNotFound) {
        // Handle the error.
    } }];
NSLog(@"Retrieved %d items", (int)rCount);

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).

1384 questions
101
votes
1 answer

Implementing Fast and Efficient Core Data Import on iOS 5

Question: How do I get my child context to see changes persisted on the parent context so that they trigger my NSFetchedResultsController to update the UI? Here's the setup: You've got an app that downloads and adds lots of XML data (about 2 million…
91
votes
3 answers

Core Data background context best practice

I have a large import task I need to do with core data. Let say my core data model look like this: Car ---- identifier type I fetch a list of car info JSON from my server and then I want to sync it with my core data Car object, meaning: If its a…
Eyal
  • 10,777
  • 18
  • 78
  • 130
75
votes
12 answers

Multiple NSEntityDescriptions Claim NSManagedObject Subclass

I am creating a framework that allows me to use Core Data. In the framework's test target, I have configured a data model named MockModel.xcdatamodeld. It contains a single entity named MockManaged that has a single Date property. So that I can test…
Nick Kohrn
  • 5,779
  • 3
  • 29
  • 49
68
votes
2 answers

What is NSManagedObjectContext's performBlock: used for?

In iOS 5, NSManagedObjectContext has a couple of new methods, performBlock: and performBlockAndWait:. What are these methods actually used for? What do they replace in older versions? What kind of blocks are supposed to be passed to them? How do I…
nevan king
  • 112,709
  • 45
  • 203
  • 241
58
votes
3 answers

How can I track/observe all changes within a subgraph?

I have a NSManagedObjectContext in which I have a number of subclasses of NSManagedObjects such that some are containers for others. What I'd like to do is watch a top-level object to be notified of any changes to any of its properties,…
David Carney
  • 2,200
  • 1
  • 19
  • 28
57
votes
5 answers

How do I copy or move an NSManagedObject from one context to another?

I have what I assume is a fairly standard setup, with one scratchpad MOC which is never saved (containing a bunch of objects downloaded from the web) and another permanent MOC which persists objects. When the user selects an object from scratchMOC…
35
votes
5 answers

CoreData could not fulfill a fault for

I have a really annoying problem, which I just can't seem to get fixed. I have a view when I send a message that gets saved to the Core Data, when thats done it asked the database for a random message (sentence) and saved that as well to an other…
Paul Peelen
  • 10,073
  • 15
  • 85
  • 168
34
votes
4 answers

Core Data viewContext not receiving updates from newBackgroundContext() with NSFetchedResultsController

In my application, I have a NSFetchedResultsController to load Core Data objects in a UITableView. The fetch request associated with this FRC uses the new viewContext property available for the NSPersistentContainer (iOS10). When I select a cell, I…
34
votes
2 answers

When to use Core Data's NSMainQueueConcurrencyType?

Is initializing a NSManagedObjectContext using NSMainQueueConcurrencyType only for the situation where that MOC has a child MOC that was initialized using NSPrivateQueueConcurrencyType? To give some background: my app has a traditional structure…
John Topley
  • 113,588
  • 46
  • 195
  • 237
32
votes
7 answers

Core Data nested managed object contexts and frequent deadlocks / freezes

I have a problem that is almost identical to the problem described by this person here, but it hasn't get answered: http://www.cocoabuilder.com/archive/cocoa/312683-core-data-nested-managed-object-contexts-and-frequent-deadlocks.html#312683 Here is…
30
votes
1 answer

Behavior differences between performBlock: and performBlockAndWait:?

I'm creating an NSManagedObjectContext in a private queue to handle data updates I take from files and/or services: NSManagedObjectContext *privateContext = [[NSManagedObjectContext alloc]…
AppsDev
  • 12,319
  • 23
  • 93
  • 186
30
votes
3 answers

Core Data: Do child contexts ever get permanent objectIDs for newly inserted objects?

I have an app with two managed object contexts setup like this: Parent Context: NSPrivateQueueConcurrencyType, linked to the persistent store. Main Context: NSMainQueueConcurrencyType, child of Parent Context. When insert a new managed object to…
Jorge
  • 2,530
  • 1
  • 19
  • 28
29
votes
2 answers

NSManagedObjectContext(): `init()` was deprecated in iOS 9.0: Use -initWithConcurrencyType

I was working through Core Data Stack in Swift - Demystified but when I got to the line self.context = NSManagedObjectContext() I got the warning `init()` was deprecated in iOS 9.0: Use -initWithConcurrencyType: instead I see that I can do one of…
Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393
28
votes
3 answers

Changing a managed object property doesn't trigger NSFetchedResultsController to update the table view

I have a fetchedResultsController with a predicate, where "isOpen == YES" When calling for closeCurrentClockSet, I set that property to NO. Therefore, it should no longer appear on my tableView. For Some Reason, this is not happening. Can someone…
27
votes
3 answers

Correct implementation of parent/child NSManagedObjectContext

My app sometimes inserts objects into the managed object context that are not meant to necessarily be saved. For example, when I launch an 'add entity' modal, I create a managed object and assign it to the modal. If the user saves from that modal, I…
Ben Packard
  • 26,102
  • 25
  • 102
  • 183
1
2 3
92 93