Issue #686
I now use Core Data more often now. Here is how I usually use it, for example in Push Hero
From iOS 10 and macOS 10.12, NSPersistentContainer that simplifies Core Data setup quite a lot. I usually use 1 NSPersistentContainer
and its viewContext
together with newBackgroundContext
attached to that NSPersistentContainer
In Core Data, each context has a queue, except for viewContext
using the DispatchQueue.main
, and each NSManagedObject
retrieved from 1 context is supposed to use within that context queue only, except for objectId
property.
Although NSManagedObject
subclasses from NSObject
, it has a lot of other constraints that we need to be aware of. So it’s safe to treat Core Data as a cache layer, and use our own model on top of it. I usually perform operations on background context to avoid main thread blocking, and automaticallyMergesChangesFromParent
handles merge changes automatically for us.
extension SendHistoryItem {
func toCoreData(context: NSManagedObjectContext) {
context.perform {
let cd = CDSendHistoryItem(context: context)
}
}
}
extension CDSendHistoryItem {
func toModel() throws -> SendHistoryItem {
}
}
final class CoreDataManager {
private var backgroundContext: NSManagedObjectContext?
init() {
self.backgroundContext = self.persistentContainer.newBackgroundContext()
}
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "PushHero")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error {
print(error)
}
})
return container
}()
func load(request: NSFetchRequest<CDSendHistoryItem>, completion: @escaping ([SendHistoryItem]) -> Void) {
guard let context = CoreDataManager.shared.backgroundContext else { return }
context.perform {
do {
let cdItems = try request.execute()
let items = cdItems.compactMap({ try? $0.toModel() })
completion(items)
} catch {
completion([])
}
}
}
func save(items: [SendHistoryItem]) {
guard let context = backgroundContext else {
return
}
context.perform {
items.forEach {
let _ = $0.toCoreData(context: context)
}
do {
try context.save()
} catch {
print(error)
}
}
}
}
Read more
Updated at 2020-10-25 20:58:07