Изменить загруженный NSPersistentContainer - PullRequest
0 голосов
/ 09 января 2019

Я создал одноэлементный класс для управления основными данными:

class CoreDataManager {
static let sharedManager = CoreDataManager()

private init() {}

lazy var persistentContainer: NSPersistentContainer = {
    let container = NSPersistentContainer(name: "MyContainer")
    if Globals.profileNumber != 0 {
        let alternateURL = NSPersistentContainer.defaultDirectoryURL()
        let storeURL = alternateURL.appendingPathComponent("\(Globals.profileNumber)MyContainer.sqlite")
        let storeDescription = NSPersistentStoreDescription(url: storeURL)
        container.persistentStoreDescriptions = [storeDescription]
    }
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    })
    return container
}()

// MARK: - Core Data Saving support

func saveContext () {
    let context = persistentContainer.viewContext
    if context.hasChanges {
        do {
            try context.save()
        } catch {
            let nserror = error as NSError
            fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
        }
    }
}
}

Но как бы я сменил, на какое хранилище указывает persistentContainer, позже в приложении?

Например, пользователь загружает приложение, входит в систему и загружает файл sqlite по умолчанию. Затем пользователь переключается на другую учетную запись пользователя, которая затем должна «закрыть» текущую базу данных, а затем persistentContainer необходимо загрузить другое хранилище?

1 Ответ

0 голосов
/ 15 января 2019

Как упомянуто в ссылке, предоставленной klaudas, хорошей альтернативой является наличие одного стека, в котором сущности имеют отношения к пользователям.

Если вы хотите иметь отдельные магазины, вы можете попробовать что-то вроде этого:

class CoreDataManager {
    // The rest of your class...

    private(set) var persistentContainer: NSPersistentContainer?

    func setupNewPersistentContainer(completionHandler: @escaping (_ success: Bool) -> Void) {
        let container = NSPersistentContainer(name: "MyContainer")
        // You should also handle the case where profileNumber == 0 and your store URL can't be constructed.
        if Globals.profileNumber != 0 {
            let alternateURL = NSPersistentContainer.defaultDirectoryURL()
            let storeURL = alternateURL.appendingPathComponent("\(Globals.profileNumber)MyContainer.sqlite")
            let storeDescription = NSPersistentStoreDescription(url: storeURL)
            container.persistentStoreDescriptions = [storeDescription]
        }

        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                // Handle the error.
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }

            let success: Bool = error == nil
            completionHandler(success)
        })

        persistentContainer = container
    }

    // The rest of your class...
}

По сути, вы помещаете логику настройки контейнера в функцию, которую вы вызываете при первой инициализации стека, а затем при переключении учетных записей. Вы можете настроить класс так, чтобы сделать persistentContainer необязательным, или добавить флаг, который отслеживает успешную загрузку хранилища.

Есть несколько вещей, на которые стоит обратить внимание:

  1. При таком подходе вам также необходимо обновить все выбранные контроллеры результатов и управляемые объекты, которые вы храните в памяти (поскольку их постоянное хранилище больше недоступно). Самый простой способ - сбросить весь пользовательский интерфейс при переключении.

  2. Когда вы настраиваете новый контейнер, дождитесь обработчика завершения, прежде чем продолжить поток смены учетной записи.

  3. Если у вас есть какие-либо ссылки на управляемые объекты, вы можете проверить, являются ли они действительными в контексте, проверив object.managedObjectContext?.persistentStoreCoordinator == context.persistentStoreCoordinator.

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