Как правильно использовать Core Data managedObjectContext и правильно сохранить контекст? - PullRequest
0 голосов
/ 30 мая 2018

В моем приложении есть специальный класс CoreDataManager , который отвечает за все операции с основными данными в моем приложении.

Первые строки в CoreDataManager Класс выглядят так:

   static var sharedInstance: CoreDataManager = { // or private static var
        let instance = CoreDataManager()
        return instance
    }()

    // Init
    override init() {
        self.persistentContainer = NSPersistentContainer.init(name: "AppName")
        self.persistentContainer.loadPersistentStores { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("CoreDataManager: init, loadPersistentStores error: \(error), \(error.userInfo)")
            } else {
                print("CoreDataManager: init() func finished with Success!")


            }
        }

        self.persistentContainer.viewContext.undoManager = nil 
        self.persistentContainer.viewContext.shouldDeleteInaccessibleFaults = true
        self.persistentContainer.viewContext.automaticallyMergesChangesFromParent = true

    }

    let persistentContainer: NSPersistentContainer
    var viewContext: NSManagedObjectContext? {
        return self.persistentContainer.viewContext
    }


    func saveViewContext() {

        let context = self.viewContext

        if self.viewContext != nil {

            if context!.hasChanges {
                do {
                    try context!.save()

                } catch {

                    let nserror = error as NSError
                    fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
                }

            }


        }

Когда мне нужно сохранить, отредактировать или удалить объекты основных данных в моем приложении, я вызываю одиночный кодкласса CoreDataManager и методов (сохранения, редактирования, удаления сущностей), объявленных в этом классе.

В моем приложении у меня также есть LocalNotificationManager , где явыполнять некоторые операции с CoreData сущностями, когда я получаю изменения от CloudKit или когда я удаляю некоторые сущности.Я звоню CoreDataManager.sharedInstance.saveViewContext(), когда хочу сохранить изменения, и "думаю, что я делаю это неправильно, потому что иногда я получаю ошибки.

Я не совсем понимаю, как правильно вызвать контекст и сохранить егои задайте следующие вопросы:

При сохранении, редактировании, удалении вызовов я должен использовать / сохранять mainContext или privateContext ?

Когдаполученные уведомления, следует ли мне использовать / save mainContext или privateContext ?

Когда мне следует сохранять viewContext из основного потока и когда использовать контекст закрытого управляемого объекта?Я использую .MainQueueConcurrencyType или я могу избежать этого?

Должен ли я объявить переменную privateObjectContext в моем классе CoreDataManager и это правильный путь?чтобы сделать это?

Я видел, что закрытый контекст может быть объявлен таким образом, но могу ли я реализовать его в своем классе CoreDataManager и когда мне следует вызывать его вместо saveViewContext().

 let moc = NSManagedObjectContext(concurrencyType:.MainQueueConcurrencyType)
 let privateMOC = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
 privateMOC.parentContext = moc
 privateMOC.performBlock({
     do {
         try privateMOC.save()
     } catch {
         fatalError("Failure to save context: \(error)")
     }
     })

Можетобъясните, как правильно использовать сохранение контекста в разных ситуациях?

Swift 4, Xcode 9.

1 Ответ

0 голосов
/ 30 мая 2018

У вас есть два варианта:

Простой способ

Чтение и запись ТОЛЬКО в viewContext и ТОЛЬКО из основного потока.Это будет работать, но если у вас есть много данных, которые вы читаете или пишете одновременно, это заблокирует ваш пользовательский интерфейс.Если у вас есть приложение с небольшим количеством материала, хранящегося в основных данных, оно будет работать нормально и, безусловно, является самым простым вариантом.

Сложный способ

Все чтение выполняется с помощьюviewContext, но НИКОГДА не пишите в него.Доступ только к viewContext из основного потока.Делайте все ваши записи с persistentContainer.performBackgroundTask и используйте контекст, который был передан в блок.Не используйте никакие другие управляемые объекты внутри этого блока.Если вам нужно передать objectId и выполнить выборку внутри блока.Не пропускайте никаких предметов за пределы этих блоков.Если вы обнаружите, что вам нужно, то используйте objectId.Вам также необходимо создать операцию Queue и обернуть в нее все ваши вызовы performBackgroundTask, чтобы не возникали конфликты записи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...