Я сталкиваюсь с этой проблемой один или два раза в день в течение последней недели, когда я открываю свое приложение, и приложение пытается выполнить любую операцию сохранения в контексте, я все еще не могу найти способ воспроизвести ее.
Я искал много вопросов по SO для исправления, но большинство из них указывают на проблемы 2
Проблема переноса основных данных (которой у меня нет, так как я использую ту же версию модели, нет .)
сбой при загрузке постоянного хранилища (что также не происходит в моем случае, поскольку мой базовый стек данных не инициализирует основной пользовательский интерфейс, если метод loadPersistentStores
включен ошибка persistentContainer)
Я использую настройку стека основных данных, указанную в приведенной ниже ссылке: https://williamboles.me/progressive-core-data-migration/
Вот моя установка CoreData класс:
lazy var persistentContainer: NSPersistentContainer = {
let persistentContainer = NSPersistentContainer(name: "ABC")
let description = persistentContainer.persistentStoreDescriptions.first
description?.shouldInferMappingModelAutomatically = false //inferred mapping will be handled else where
description?.shouldMigrateStoreAutomatically = false
description?.type = storeType
return persistentContainer
}()
lazy var managedObjectContext: NSManagedObjectContext = {
let context = self.persistentContainer.newBackgroundContext()
context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
context.automaticallyMergesChangesFromParent = true
return context
}()
lazy var _managedObjectContext: NSManagedObjectContext = {
let context = self.persistentContainer.viewContext
context.automaticallyMergesChangesFromParent = true
return context
}()
// MARK: - Singleton
private static var privateShared : CoreDataManager?
class func shared() -> CoreDataManager { // change class to final to prevent override
guard let uwShared = privateShared else {
privateShared = CoreDataManager()
return privateShared!
}
return uwShared
}
class func destroy() {
privateShared = nil
}
// MARK: - Init
init(storeType: String = NSSQLiteStoreType, migrator: CoreDataMigratorProtocol = CoreDataMigrator()) {
self.storeType = storeType
self.migrator = migrator
}
// MARK: - SetUp
func setup(completion: @escaping () -> Void) {
loadPersistentStore {
completion()
}
}
// MARK: - Loading
private func loadPersistentStore(completion: @escaping () -> Void) {
migrateStoreIfNeeded {
self.persistentContainer.loadPersistentStores { description, error in
guard error == nil else {
fatalError("was unable to load store \(error!)")
}
completion()
}
}
}
private func migrateStoreIfNeeded(completion: @escaping () -> Void) {
guard let storeURL = persistentContainer.persistentStoreDescriptions.first?.url else {
fatalError("persistentContainer was not set up properly")
}
if migrator.requiresMigration(at: storeURL, toVersion: CoreDataMigrationVersion.current) {
DispatchQueue.global(qos: .userInitiated).async {
self.migrator.migrateStore(at: storeURL, toVersion: CoreDataMigrationVersion.current)
DispatchQueue.main.async {
completion()
}
}
} else {
completion()
}
}
И я инициализирую стек Базовых данных, используя следующий код в делегате приложения:
CoreDataManager.shared().setup {[unowned self] in
self.showMainUI()
}
Мое приложение падает после загрузки контроллера домена и некоторой части моего код выполняет операцию сохранения на определенной модели NSManagedObject
Это способ сохранения в Context:
let context = CoreDataManager.shared().managedObjectContext // background context
context.performAndWait {
if let entityDescription = NSEntityDescription.entity(forEntityName: Entity_Name, in: context) {
if let runEntityObject = NSManagedObject(entity: entityDescription, insertInto: context) as? MY_Model {
// Create the Object
guard context.hasChanges else { return }
do {
try context.save() // Crashes here once or twice a day :(
}
catch {
print(error.localizedDescription)
}
}
}
}
В некоторых ответах SO также упоминаются проблемы с многопоточностью, но я использую блок executeAndWait, поэтому сохранение происходит в той же очереди
очень полезно, если кто-то указал мне правильное направление по этому вопросу