【发布时间】:2017-10-21 06:02:13
【问题描述】:
当多个上下文同时保存时,我尽量避免崩溃。
以下类有一个操作队列,同时只操作一项工作。它具有三个上下文。首先,defaultContext 是主队列类型,它不直接更新,只对用户可见。另外两个上下文是localContext和externalContext。
LocalContext 用于用户的日程添加,外部 Context 用于外部日程更新,如云同步。本地上下文和外部上下文是 defaultContext 的子级,并将它的自动MergesChangesFromParent 属性设置为 true。即使同时执行用户更新和外部更新。由于它们在同一个队列中按顺序运行,因此不会丢失数据。
当数据输入很小的时候效果很好。但是当数据过多时,应用程序会变慢。有没有更好的方法?
这是我的代码。
class DataController {
static let shared = DataController()
var schedules: [Schedule] = []
var persistentContainer: NSPersistentContainer
let persistentContainerQueue = OperationQueue()
private init() {
persistentContainerQueue.maxConcurrentOperationCount = 1
persistentContainer = NSPersistentContainer(name: "CoreDataConcurrency")
persistentContainer.loadPersistentStores { (description, error) in
if let error = error {
fatalError("Failed to load Core Data stack: \(error)")
}
}
}
lazy var defaultContext: NSManagedObjectContext = {
[unowned self] in
self.persistentContainer.viewContext
}()
lazy var localContext: NSManagedObjectContext = {
[unowned self] in
let context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
context.parent = self.defaultContext
context.automaticallyMergesChangesFromParent = true
return context
}()
lazy var externalContext: NSManagedObjectContext = {
[unowned self] in
let context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
context.parent = self.defaultContext
context.automaticallyMergesChangesFromParent = true
return context
}()
func enqueueCoreDataOperation(context: NSManagedObjectContext, changeBlock: @escaping () -> (NSManagedObjectContext)) {
persistentContainerQueue.addOperation {
let changedContext = changeBlock()
guard changedContext.hasChanges else {
return
}
changedContext.performAndWait({
do {
try changedContext.save()
if let parentContext = changedContext.parent {
do {
try parentContext.save()
} catch {
fatalError()
}
}
} catch {
fatalError()
}
})
}
}
func addSchedule(title: String, date: Date, context: NSManagedObjectContext) {
let changeBlock: () -> (NSManagedObjectContext) = {
let schedule = NSEntityDescription.insertNewObject(forEntityName: "Schedule", into: context) as! Schedule
schedule.title = title
schedule.date = date
return context
}
enqueueCoreDataOperation(context: context, changeBlock: changeBlock)
}
func updateSchedule(schedule: Schedule, modifiedTitle: String, context: NSManagedObjectContext) {
let scheduleInContext = context.object(with: schedule.objectID) as! Schedule
let changeBlock: () -> (NSManagedObjectContext) = {
scheduleInContext.title = modifiedTitle
return context
}
enqueueCoreDataOperation(context: context, changeBlock: changeBlock)
}
}
【问题讨论】:
标签: ios swift core-data concurrency