When we create a new project in Xcode with the Core Data option checked, it generates a new project defining Core Data stack on AppDelegate.swift:
class AppDelegate: UIResponder, UIApplicationDelegate {
// ...
// MARK: - Core Data stack
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "CoreDataTest")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
// MARK: - Core Data Saving support
func saveContext () {
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
}
For me to easily access persistentContainer, I've also added this piece of code:
static var persistentContainer: NSPersistentContainer {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { fatalError("Could not convert delegate to AppDelegate") }
return appDelegate.persistentContainer
}
So I can call it like this:
let container = AppDelegate.persistentContainer
The problem happens when I try to access it from a background thread. For example, I have a piece of code that runs in the background and fetches some data from a web service. When it gets the data, I'm saving it using:
static func loadData(_ id: String) {
fetchDataOnBackground(id: id) { (error, response) in
if let error = error {
// handle...
return
}
guard let data = response?.data else { return }
let container = AppDelegate.persistentContainer // Here
container.performBackgroundTask({ context in
// save data...
})
}
}
When I try to get the persistent container, it generates on the console:
Main Thread Checker: UI API called on a background thread: -[UIApplication delegate]
For this to not happen anymore, I've changed my persistentContainer from lazy var to static on AppDelegate:
static var persistentContainer: NSPersistentContainer = {
// same code as before...
}()
And the error doesn't happen anymore.
But I'm wondering if this can have any side effects that I'm not aware of. I mean, I would have only one persistentContainer anyway, because there's only one instance of AppDelegate right? So I can change it to static like I did and access it using AppDelegate.persistentContainer on other parts of my app without any problems?
Or is there another recommended pattern to handle persistentContainer instantiation and usage?