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.
Using multiple background contexts may seem like a good idea because it allows data to be modified simultaneously from different threads. However, doing so increases the complexity of the program. Properly configuring Core Data’s merge policies to handle all possible cases can be tricky, which may lead to 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 line 78 is uncommented, because it sets a merge policy that resolves conflicts by keeping the persisted version instead of the newer changes. However, a more practical approach is to use a single background context for all modifications, executing them sequentially. This simplifies concurrency handling and avoids merge conflicts, making the code 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 would pass without merge conflicts.
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