Skip to content
kevindelord edited this page Mar 2, 2016 · 8 revisions

One Default Context

Since MagicalRecord 2.3 the logic around the NSManagedObjectContext did change quite a bit.

When working with Core Data, you will need to deal with NSManagedObjectContext.

Nicely, MagicalRecord initializes, provides and uses a default NSManagedObjectContext object throughout your app.

This default context operates on the main thread, and is great for simple, single-threaded apps.

All this means that if you want to retrieve an entity on the main thread you can directly call the MagicalRecord functions. The default context will be used:

Plane.MR_findFirst()

This will be the same as:

Plane.MR_findFirstInContext(NSManagedObjectContext.MR_defaultContext())

Saving Contexts

All saving functions provided are executed on a background thread. This way, your database management will not impact the UI performance of your app.

Those functions provide a new NSManagedObjectContext. This context must be used to CRUD your entities. In the end this context will be 'merge' into the default one.

TODO: picture

Asynchronous Save

Because the saving block in executed on another thread using another context, you need to retrieve the entities you want to use and/or update.

DKDBManager.saveWithBlock { (savingContext: NSManagedObjectContext) in
	// Executed on background thread
	var localPlane = self.availablePlane.entityInContext(savingContext)
	localPlane?.origin = "Tokyo"
	localPlane?.destination = "London"
}

At the end of this block, all performed operations will be 'merged' into the Default Context and usable on the main thread.

Documentation: DKDBManager.saveWithBlock:

Asynchronous Save With Completion

To perform an action after this save block is completed, you can fill in a completion block:

DKDBManager.saveWithBlock({ (savingContext: NSManagedObjectContext) in
	// Executed on background thread
	var localPlane = self.availablePlane.entityInContext(savingContext)
	localPlane?.origin = "Tokyo"
	localPlane?.destination = "London"

}, completion: { (didSave: Bool, error: NSError?) in
	// Executed on main thread
	self.tableView.reloadData()
})

As the completion block is called on the main thread, it is safe to trigger UI updates.

Documentation: DKDBManager.saveWithBlock:completion:

Synchronous Save

It is also possible to synchronously executes and saves modifications into the persistent store.

Be careful when performing saving operations on the main thread, it could slow down your application.

Nonetheless, this is very useful when you're managing your own threads/queues and need a serial call to create or change data.

DKDBManager.saveWithBlockAndWait { (savingContext: NSManagedObjectContext) in
	// Executed on main thread
	var localPlane = self.availablePlane.entityInContext(savingContext)
	localPlane?.origin = "Tokyo"
	localPlane?.destination = "London"
}
self.tableView.reloadData()

Documentation: DKDBManager.saveWithBlockAndWait

Manually create new contexts

In case you would like to create or manually deal with NSManagedObjectContext for non-main threads usage, please refer to the official documentation.

Make it small!

It is highly recommended to only save small amount of changes to the persistent store.

From the MagicalRecord documentation:

Break the task down into smaller saves: Tasks like importing large amounts of data should always be broken down into smaller chunks. There's no one-size-fits all rule for how much data you should be saving in one go, so you'll need to measure your application's performance using a tool like Apple's Instruments and tune appropriately.

Clone this wiki locally