Note that there are some explanatory texts on larger screens.

plurals
  1. POPitfalls of using two persistent store coordinators for efficient background updates
    text
    copied!<p>I am searching for the best possible way to update a fairly large core-data based dataset in the background, with as little effect on the application UI (main thread) as possible. </p> <p>There's some good material available on this topic including:</p> <ul> <li><a href="https://developer.apple.com/wwdc/videos/" rel="noreferrer">Session 211 from WWDC 2013</a> (Core Data Performance Optimization and Debugging, from around 25:30 onwards)</li> <li><a href="http://www.objc.io/issue-4/importing-large-data-sets-into-core-data.html" rel="noreferrer">Importing Large Data Sets from objc.io</a></li> <li><a href="http://www.objc.io/issue-2/common-background-practices.html" rel="noreferrer">Common Background Practices from objc.io</a> (Core Data in the Background)</li> <li><a href="http://floriankugler.com/blog/2013/5/11/backstage-with-nested-managed-object-contexts" rel="noreferrer">Backstage with Nested Managed Object Contexts</a></li> </ul> <p>Based on my research and personal experience, the best option available is to effectively use two separate core-data stacks that only share data at the database (SQLite) level. This means that we need two separate <code>NSPersistentStoreCoordinators</code>, each of them having it's own <code>NSManagedObjectContext</code>. With write-ahead logging enabled on the database (default from iOS 7 onwards), the need for locking could be avoided in almost all cases (except when we have two or more simultaneous writes, which is not likely in my scenario). </p> <p>In order to do efficient background updates and conserve memory, one also needs to process data in batches and periodically save the background context, so the dirty objects get stored to the database and flushed from memory. One can use the <code>NSManagedObjectContextDidSaveNotification</code> that gets generated at this point to merge the background changes into the main context, but in general you don't want to update your UI immediately after a batch has been saved. You want to wait until the background job is completely done and than refresh the UI (recommended in both the WWDC session and objc.io articles). This effectively means that the application main context remains out of sync with the database for a certain time period. </p> <p>All this leads me to my main question, which is, <strong>what can go wrong, if I changed the database in this manner, without immediately telling the main context to merge changes?</strong> I'm assuming it's not all sunshine an roses.</p> <p>One specific scenario that I have in my head is, what happens if a fault needs to be fulfilled for an object loaded in the main context, if the background operation has in between deleted that object from the database? Can this for instance happen on a NSFetchedResultsController based table view that uses a batchSize to fetch objects incrementally into memory? I.e., an object that has not yet been fully fetched gets deleted but than we scroll up to a point where the object needs to get loaded. Is this a potential problem? Can other things go wrong? I'd appreciate any input on this matter. </p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload