Issue #785

Core Data

Calling mergeChanges on a managed object context will automatically refresh any managed objects that have changed. This ensures that your context always contains all the latest information. Note that you don’t have to call mergeChanges on a viewContext when you set its automaticallyMergesChangesFromParent property to true. In that case, Core Data will handle the merge on your behalf.

Managed objects retrieved from a context are bound to the same queue that the context is bound to.

The ability to have a child MOC is neat in some corner cases. Let’s review the core functionality of MOCs in order to understand those cases:

  • MOCs load objects from its source (a PSC or another MOC)
  • MOCs save objects to its source (a PSC or another MOC)
  • MOCs enforce graph integrity when they save

Use Core Data as a local cache

Parent/child contexts are usually advocated for something like “load some data in the background, and the saving it pushes it to the main queue context”. That can work, but it does mean that in order to persist your data, you actually have to save two contexts, instead of just one (because save()-ing a context only pushes the data up one level. For a child context, the data only goes to the parent context, not all the way up to the PSC). In my opinion, using a child context like this is unnecessarily complicated.

For general, non-transactional usage, I think it’s better to have two contexts (one for the main thread, one for the background) that both link directly to the PSC. Importation of data is done on the background context, and when it saves, the main queue listens for the NSManagedObjectContextDidSave notification and merges in the changes with .mergeChanges(fromContextDidSave:) method to update its internally-held objects. Even that step might be unnecessary if the context has automaticallyMergesChangesFromParent set to true.

While you can fetch data from Core Data with @FetchRequest just fine, I tend to avoid it in my apps. The main reason for this is that I’ve always tried to separate my Core Data code from the rest of my application as much as possible.

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

When you execute an instance of NSFetchRequest, it always accesses the underlying persistent stores to retrieve the latest results.

This can be misleading. When one see parent store he can understand the parent persitent store of my context hierarchy. However, what is meant by parent store is either: the persistentStoreCoordinator or the parentContext So, if your context was setup with a parent context, changes are commited to his parent but no further. To save it to the persistent store, you’ll need to call save() on contexts all the way up in the hierarchy until you reach the persistent store.

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

An object that meets the criteria specified by request (it is an instance of the entity specified by the request, and it matches the request’s predicate if there is one) and that has been inserted into a context but which is not yet saved to a persistent store, is retrieved if the fetch request is executed on that context.

Changes are not reflected in the context". So what you’re seeing is normal. Batch updates work directly on the persistent store file instead of going through the managed object context, so the context doesn’t know about them. When you delete the objects by fetching and then deleting, you’re working through the context, so it knows about the changes you’re making (in fact it’s performing those changes for you).

mainContext would fetch all the way to the persistent store. Fetches and objectWithID: only go as many levels as they need to. It’s important to remember that when a context is created it’s a “snapshot” of the state of it’s parent. Subsequent changes to the parent will not be visible in the child unless the child is somehow invalidated

CloudKit

NSFetchedResultsController

Performance

How to fetch with background context

core data

Approach 1: Treat Core Data as cache

Pros

  • backgroundContext.automaticallyMergesChangesFromParent
  • Use 1 shared background context to load and updates changes
  • Convert NSManagedObject to struct
  • Our struct can have additional logic and properties
  • Does not need to care about faulting

Cons

  • Need to update objectId When context.save, NSManagedObject ’s objecteId is updated
  • Need to reload when underlying NSManagedObject changes
  • Need to handle relationship

Instead of plain NSFetchRequest, can use NSFetchedResultsController on background context. In its controllerDidChangeContent convert to struct

Approach 2: viewContext to persistent coordinator

viewContext -> persistent coordinator <- backgroundContext

Pros

  • viewContext.automaticallyMergesChangesFromParent
  • viewContext and background Context stems from persistent container
  • background context changes object
  • viewContext read only

Cons

To import data in the background, apps need two managed object contexts (NSManagedObjectContext): a main queue context to provide data to the user interface, and a private queue context to perform the import on a background queue. Both contexts are connected to the same persistentStoreCoordinator. This configuration is more efficient than using a nested context.

Approach 3: viewContext to background context

viewContext -> backgroundContext -> persistent coordinator

Pros

  • viewContext.automaticallyMergesChangesFromParent
  • viewContext reads from backgroundContext, no main queue block
  • backgroundContext changes

Cons

  • If there’s changes in viewContext, need to save viewContext first before saving parent context

Read more

Approach 4: background context -> mainContext -> backgroundContext -> persistent coordinator

https://stackoverflow.com/questions/35961936/child-nsmanagedobjectcontext-update-from-parent

RootContext (private queue) - saves to persistent store
MainContext (main queue) child of RootContext - use for UI (FRC)
WorkerContext (private queue) - child of MainContext - use for updates & inserts