How to use Core Data, thread-safe, using Async/Await
With the introduction of Async/Await it has become much easier for iOS developers to work using Background Queues. Fetching data in the background can vastly improve app performance.
It’s a good idea to perform all Core Data fetching in the background to keep the main thread free for UI tasks. One
get A function like below would be ideal:
func get(request: NSFetchRequest
) async -> [NSManagedObject]
GCD will do all the work for us and fetch the data in a background thread. unfortunately core data is No thread safe.
I don’t want to say that Core Data is bad, quite the opposite. Core Data is extremely fast, well maintained and has been with us since iOS 3.0.
The point is that CoreData needs to be handled with care, especially now that concurrency has become much easier to use.
To make sure that every access we make a
NSManagedObject is thread safe we need to do it in object
NSManagedObjectContext, The proposed way is to do it using context
func perform(_ block: @escaping () -> Void)
every time a
NSManagedObject is accessed in a different thread than the thread of its context, it can potentially cause a crash. To test when this is the case, just add the following launch logic.
how are we doing UXMA Germany avoid such issues? We are using NSManagedObjects to store and retrieve data but not anywhere else in our code. as soon as possible
FetchRequest When executed we convert the Core Data entity to an immutable, thread-safe, object.
Item We define an immutable object – in this case, a structure with the same name that is thread safe – named
Now we define the protocol
ToSafeObject, Thing conforms to this protocol and we use
safeObject() its method of converting unsafe
Item object to vault
a simple extension function on
NSManagedObjectContext class that accepts a
NSFetchRequest where e is a
NSManagedObject which correspond to
ToSafeObject manners. This function is async and returns an array of
SafeObjects for given
Using this technique we are always thread-safe, and we can actually use a background context to retrieve all Core Data entities in a background thread.
The new get function is async so we need to use await to test it.
If, in this unit test, we add
-com.apple.CoreData.ConcurrencyDebug 1 Comment out the launch argument and line 26 we will see that the app crashes. Exactly because we are fetching data on wrong thread.
Little tricks like this help us uxmaTo deliver better quality apps for our customers and of course to get less crash reports.
As always, Happy Coding!
salute to Christian’s