Core Data framework provides generalized and automated solutions to common tasks associated with object life-‐cycle and object graph management, including persistence. http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/CoreData/Articles/cdTechnologyOverview.html#//apple_ref/doc/uid/TP40009296-SW1
readable + good for apps requiring simple storage scenarios (=most apps, probably) + hides complexity - hides complexity - easy to start, but diving deeper becomes harder - uses defaults that are suboptimal in a multithreaded app - concurrency errors and issues are subtle
will speed up your Core Data development by several factors. ‣ Also: take a look at mogenerator: ‣ http://rentzsch.github.com/mogenerator/ ‣ or: brew install mogenerator
used to power the UI must be fetched on the UI thread. ‣ Heavy/complex fetch requests (queries) block the UI thread while fetching the objects. You don’t want that.
NSManagedObjectContext “locks” an object when you read one of its properties. ‣ This can cause a deadlock when you do access the same data from 2 threads. ‣ Reason: faulting support can change the object even while just reading from it. ‣ You can’t turn it off.
‣ Be very careful when going from one thread to another. ! ‣ MagicalRecord tries to hide this from you: ‣ It automatically provides a context for each thread ‣ This is a bit counterintuitive since you start mixing objects across threads quite easily.
Dispatch and dispatch queues ‣ Core Data manages threading for you ‣ Better than thread confinement ‣ more straightforward ‣ more flexible ! ‣ MagicalRecord hides this from you, too. ‣ Automatically switches to dispatch queues on iOS5 even though the API remains the same.
‣ NSPrivateQueueConcurrencyType ‣ The context has its own private dispatch queue ‣ NSMainQueueConcurrencyType ‣ The context is associated with the main queue (or runloop, or UI thread) parentMoc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; [parentMoc setPersistentStoreCoordinator:coordinator]; ! moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; moc.parentContext = parentMoc;
block you provide on the queue associated with the context. ‣ Object access in the block is thread safe [context performBlockAndWait:^{ for (Room* room in [Room findAllInContext:context]) { room.joinedUsers = [NSSet set]; room.knowsAboutJoinedUsersValue = NO; room.unreadCountValue = 0; room.status = @""; } NSError* error = nil; [context save:&error]; }];
block on the context dispatch queue as soon as possible ‣ nonblocking call ‣ code will not execute immediately ! -‐ (void)performBlockAndWait:(void (^)())block; ‣ executes the block on the context dispatch queue immediately ‣ blocks the current execution until block is done ‣ can cause a deadlock (if you’re already running code on the same queue)
which are “on their own” ‣ Consider the code in the block a Unit Of Work ‣ Best for save operations ‣ Useful for long fetches (use callbacks) ! ‣ performBlockAndWait: ‣ When you need stuff immediately ‣ Good for small fetches or “standalone” saves
thread handling, Core Data handles it for you. ‣ More flexible: as long as you access managed objects in the correct context using performBlock: you’re pretty safe ‣ also applies to the main/UI thread! (unless you’re sure you’re on the main thread)
deep. ‣ Parent contexts don’t pull changes from child contexts. ‣ Child contexts don’t see changes by parent contexts. ‣ Make them plenty and short-lived
private queue ‣ Many child contents with private queues ‣ context on main queue is child of root ‣ Actual persistence happens in background (does not block the UI)
objects. ‣ Refetch the object on a different thread or queue to work with it. ‣ Don’t forget to save the ‘original’ object first before working with it on the second thread or queue.
large queries. 1. do the heavy lifting in the background 2. pass list of NSManagedObjectIDs to another thread (e.g. UI thread). 3. load objects as faults, and let Core Data fault them in when you need them (e.g. when accessing a property) ! ‣ That’s lot of requests, but this is actually more performant and desirable in most cases.
a non-root context don’t get updated to permanent IDs when saving in the root context ‣ The object is saved just fine, but the ID is not updated correctly. ‣ When passing these around to other contexts after saving: you won’t find the object in another child context!
! ‣ Transforms objects with temporary IDs to permanent IDs (through the persistent store of the root context). ‣ Do this when creating a managed object and you’re safe. ‣ Obtaining permanentIDs is batched, so the performance hit is not that high
more “automatic” context handling --> dangerous! ‣ Added some extra sauce to work with the nested contexts. ‣ The methods MR supplies still allow for a speedup when coding.