pretty

Saturday 5 November 2022

Accessing CoreData from a single background context

The usual scheme when working with Core Data is using one or more of the background contexts for modifying data, and one viewContext for reading and displaying it.

Utilizing many background contexts may seem like a good idea at first, because it allows to modify the data simultaneously from different threads. However, using many background CoreData contexts increases the complexity of a program. It can be tricky to properly set up the CoreData Merge Policy covering all the possible cases, and hence get into the concurrency related issues.

The following unit test recreates the basic concurrency issue on purpose, when the same data entity is being modified from those two background contexts on lines 59 and 75:

The test will pass if the line 78 would be uncommented. This line sets the merge policy that, instead of throwing error, prefers the persisted field version over the newer field change. But instead of setting a specific merge policy, more viable option would be to have a single background context that executes all the modifications sequentially. It is much easier to manage and reason about.

To employ sequential CoreData writing scheme it's convenient to have a wrapper class that would hold the required single background context. The wrapper class in this sample is named CoreDataInventory and should be used for every CoreData interaction in the application. CoreDataInventory wrapper class in this design is a singleton:

Having this class let's change the unit test, and call the new method CoreDataInventory.instance.perform(...) instead of performBackgroundTask(...). The CoreData merge policy in the test is also the default one (used by CoreData when no specific policy is set), and should throw the error if there is a merge conflict.

This test should pass without merge conflicts:
	 Executed 1 test, with 0 failures (0 unexpected) in 5.023 (5.028) seconds

In conclusion, many background contexts may be used only when it is proven that concrete application performs a high amount of time-consuming data writes, and practically benefits from having multiple background contexts. Otherwise, more practical alternative is to use a single background context for writing to CoreData.

No comments :

Post a Comment