Describe a pattern for background Core Data fetches and UI updates

This tests NSManagedObjectContext concurrency and queue confinement. Strong answer: create a background context, fetch, pass objectIDs or structs to main, then main context fetches by ID to update UI. Red flag: passing NSManagedObjects across threads.
WHAT THIS TESTS: Core Data concurrency and queue confinement. Interviewers want to see that you know an NSManagedObjectContext is bound to the queue it was created on, that NSManagedObjects are not thread-safe, and that crossing these boundaries crashes or corrupts data. They also care whether you know the modern NSPersistentContainer pattern versus the older manual parent-child or independent context setups.
A GOOD ANSWER COVERS: First, create a private-queue context via NSPersistentContainer newBackgroundContext or by setting the concurrency type to NSPrivateQueueConcurrencyType. Second, wrap the fetch and any heavy processing inside perform or performAndWait so Core Data serializes the work onto that context's queue. Third, extract only safe data to pass across the thread boundary, such as NSManagedObjectID instances or plain Swift structs containing primitive values. Fourth, on the main thread, use the main-queue context to fetch by objectID or to refresh existing objects, then update the UI. If you are using parent-child contexts, the background child saves and the parent main context merges the changes, but you still should not pass the live objects across threads.
COMMON WRONG ANSWERS: Passing an NSManagedObject instance directly from the background to the main thread is the most common red flag and will crash under concurrency debugging. Another mistake is creating one shared NSManagedObjectContext and accessing it from multiple threads without perform blocks. Some candidates suggest using threadDictionary or dispatching to the main queue inside a background loop, which still violates queue confinement. A less obvious error is fetching on a background context and then calling save without handling merge conflicts or propagating changes to the main context, leaving the UI stale.
LIKELY FOLLOW-UPS: How would you handle a long-running import of thousands of rows? What merge policy do you set on the context? How does parent-child differ from independent contexts with NSPersistentContainer? What happens if you access a relationship on an NSManagedObject that was fetched on a different thread? When would you use perform versus performAndWait, and how do you avoid deadlocks?
ONE CONCRETE EXAMPLE: Suppose you need to refresh a list of messages. You call the persistentContainer newBackgroundContext method and inside the background context's perform block you execute an NSFetchRequest for Message entities. You map the results to a lightweight MessageViewModel struct containing only strings and objectIDs. You then dispatch to the main queue and pass that array to your view controller. The view controller uses the main context to call existingObject with the objectID if it needs the live object, or simply renders the view models directly. This keeps all Core Data work on the correct queues and avoids threading violations.
Source: Apple Developer Documentation
Read the original → developer.apple.com
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.