Я прочитал следующие Различия в поведении между executeBlock: и executeBlockAndWait:? Но не смог найти ответ на мой вопрос.
Следующий код взят из видео RayWenderlich .В частности, в 10: 05 код что-то примерно так:
class CoreDataStack {
var coordinator : NSPersistentStoreCoordinator
init(coordinator: NSPersistentStoreCoordinator){
self.coordinator = coordinator
}
// private, parent, in background used for saving
private lazy var savingContext : NSManagedObjectContext = {
let moc = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
moc.persistentStoreCoordinator = coordinator
return moc
}()
lazy var mainManagedObjectedContext : NSManagedObjectContext = {
let moc = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
moc.parent = self.savingContext
return moc
}()
func saveMainContext() {
guard savingContext.hasChanges || mainManagedObjectedContext.hasChanges else {
return
}
mainManagedObjectedContext.performAndWait {
do {
try mainManagedObjectedContext.save()
}catch let error{
fatalError(error.localizedDescription)
}
}
savingContext.perform {
do {
try self.savingContext.save()
}catch let error{
fatalError(error.localizedDescription)
}
}
}
}
Из того, что я понимаю, происходит то, что основной контекст просто передает изменения в свойродительский контекст, который является частным, фоновым контекстом.Это происходит синхронно.
Затем родительский частный контекст выполняет фактическое сохранение для sqlite в фоновом потоке асинхронно .Короче говоря, это очень помогает нам с производительностью.Но как насчет целостности данных?!
Представьте себе, если бы я сделал это:
let coredataManager = CoreDataStack()
coredataManager.saveMainContext() // save is done asynchronously in background queue
coredataManager.mainManagedObjectedContext.fetch(fetchrequest)
Как я могу гарантировать, что моя выборка считывает самые последние и обновленные результаты?
Если мы выполняем наши записи асинхронно, то нет ли шансов, что другое чтение одновременно может привести к неожиданным результатам, то есть результаты изменений сохранения могут или не могут быть?
РЕДАКТИРОВАТЬ: Я сделал улучшение с кодом ниже.Я могу сделать свое сохранение в параметре completeHandler.Но это не решает всей проблемы.Что делать, если я делаю fetchRequest из mainQueue где-то еще, который не знает, что одновременно происходит сохранение?
enum SaveStatus{
case noChanges
case failure
case success
}
func saveMainContext(completionHandler: (SaveStatus -> ())) {
guard savingContext.hasChanges || mainManagedObjectedContext.hasChanges else {
completionHandler(.noChanges)
return
}
mainManagedObjectedContext.performAndWait {
do {
try mainManagedObjectedContext.save()
}catch let error{
completionHandler(.failure)
fatalError(error.localizedDescription)
}
}
savingContext.perform {
do {
try self.savingContext.save()
completionHandler(.succes)
}catch let error{
completionHandler(.failure)
fatalError(error.localizedDescription)
}
}
}