Accessing CoreData asynchronously from the UI and with Networking

Hello,


I am working on a time table app for students. It will get new data from a webserver and use Core Data to save data locally.

Also I heard that you should use NSManagedContexts only from the thread where you created them.

I will have two objects that access Core Data, the webclient and the UI. The webclient will download the data and save it into Core Data, the UI will only read the saved data. The save and write operations will happen asynchronously.

My plan is the following:

1. Create a class that superviews all Data relevant operations (DataManager).

2. The DataManager has an own private concurrent queue.

3. It also has one NSManagedContext instance.

4. All CoreData related operations will be executed in the DataManager in dispatch_asyc, dispatch_sync (read-operations) and dispatch_barrier (write-operations) closures.


Data downloading procedure:

1. Download the data (background queue)

2. in a dispatch_barrier block that runs on the DataManger queue:

2a. create NSManagedObjects

2b. save the NSManagedContext


Data fetching procedure (with completion handler):

1. in a dispatch_asyc block that runs on the DataManager queue:

1a. if neccessary call the data downloading procedure

1b. fetch the requested objects from the NSManagedContext

1c. call the completion handler

Is it safe to work with Core Data in this manner?

Thanks in advance!

Answered by stefan12 in 28510022

I solved my problem using 3 contexts in this way:


private Context: writes data to file

V parent

main Context: UI updates (read only access)

V parent

private Context: downloads data from the server and saves it (read/write access)

I'm not sure if you're realizing the fact that every single attribute or relationship access (read or write) on a managed object (along with most of the managed object methods) are also an operation that needs to be subject to proper thread safety procedures.


dispatch_sync and dispatch_barrier aren't the distinction that you're looking for, because accessing new attribute values are just as likely to cause state changes in the managed object and the managed object context as write values are. Because the first access of an attribute value may end up bringing it into memory or the first access may end up accessing a pre-loaded value.

I did not know until now that an attribute or relationship might not be initialized after fetching an object. Thank you for pointing this out.


Between 1b and 1c: What if I convert all fetched objects into immutable copies and pass them over to the UI?

Is this approach better or are there better solutions?

Accepted Answer

I solved my problem using 3 contexts in this way:


private Context: writes data to file

V parent

main Context: UI updates (read only access)

V parent

private Context: downloads data from the server and saves it (read/write access)

Accessing CoreData asynchronously from the UI and with Networking
 
 
Q