Как обновить реализацию EncryptedCoreData для приложения Swift 4 (ошибка NSSQLiteErrorDomain 14)

Я делаю рефакторинг приложения обработки заказов, чтобы включить CoreData, чтобы оно могло кэшировать большие объемы данных, а некоторые данные содержат некоторые конфиденциальные данные, которые я предпочел бы зашифровать, чем нет. Это приложение будет использоваться в месте, которое является большой целью для хакеров. Поэтому я решил, прежде чем зайти слишком далеко, лучше использовать что-то вроде EncryptedCoreData для защиты базы данных.

Следовать указаниям из этой статьи оказалось сложнее, чем предполагал автор, по крайней мере, для начинающего пользователя CoreData, такого как я.

Я установил модуль и настроил соединительный заголовок, чтобы я мог получить к нему доступ в своем проекте Swift, но понятия не имею, куда должен идти код, на который он ссылается, какой URL использовать и т. Д.

Принятый ответ на подобный вопрос имеет для меня достаточно смысла, чтобы я воспроизвел его, но он не обновлен для Swift 4, и я получаю две ошибки:

lazy var persistentContainer: NSPersistentContainer = {

        let container = NSPersistentContainer(name: "DataModel")
        let containerOptions : NSDictionary = [
            EncryptedStorePassphraseKey : "someKey",
            EncryptedStore.optionFileManager() : EncryptedStoreFileManager.default()// Error: Use of unresolved identifier 'EncryptedStoreFileManager'
        ]
        let desc = try! EncryptedStore.makeDescription(options: containerOptions as! [AnyHashable : Any], configuration: nil)// Error: Type 'EncryptedStore' has no member 'makeDescription'; did you mean 'debugDescription'?
        container.persistentStoreDescriptions = [desc]
        container.loadPersistentStores(completionHandler:
            { (storeDescription, error) in
                if let error = error as NSError?
                {
                    // Replace this implementation with code to handle the error appropriately.

                    /*
                     Typical reasons for an error here include:
                     * The parent directory does not exist, cannot be created, or disallows writing.
                     * The persistent store is not accessible, due to permissions or data protection when the device is locked.
                     * The device is out of space.
                     * The store could not be migrated to the current model version.
                     Check the error message to determine what the actual problem was.
                     */
                    fatalError("Unresolved error \(error), \(error.userInfo)")
                }
            }
        )
        return container
    }()

Я могу достаточно легко решить "Ошибка: использование неразрешенного идентификатора"EncryptedStoreFileManager "", закомментировав эту часть кода - я подозреваю, что в этом больше нет необходимости. Вторая ошибка сложнее - EncryptedStoreDescription - это не тот класс, который я вижу, поэтому я не могу получить доступ к инициализатору, и у EncryptedStore больше нет метода для создания описания.

Что мне не хватает?

РЕДАКТИРОВАТЬ: Следующая попытка решения не сработала.

Я понял следующую реализацию UNTESTED, я надеюсь, что у меня будет некоторый успех. Обновлюсь, если у меня возникнут проблемы.

lazy var persistentContainer: NSPersistentContainer = {

        let container = NSPersistentContainer(name: "DataModel")
        container.loadPersistentStores(completionHandler:
            { (storeDescription, error) in
                if let error = error as NSError?
                {
                    // Replace this implementation with code to handle the error appropriately.
                    // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

                    /*
                     Typical reasons for an error here include:
                     * The parent directory does not exist, cannot be created, or disallows writing.
                     * The persistent store is not accessible, due to permissions or data protection when the device is locked.
                     * The device is out of space.
                     * The store could not be migrated to the current model version.
                     Check the error message to determine what the actual problem was.
                     */
                    fatalError("Unresolved error \(error), \(error.userInfo)")
                }
            }
        )
        do
        {
            let containerOptions : NSDictionary = [
                EncryptedStorePassphraseKey : "someKey"
            ]
            guard let appSupportDirURL = FileManager.default.urls(for:.applicationSupportDirectory, in:.userDomainMask).last else
            {
                throw RuntimeError("appSupportDirURL was nil")
            }
            try FileManager.default.createDirectory(at: appSupportDirURL, withIntermediateDirectories: true, attributes: nil)

            try container.persistentStoreCoordinator.addPersistentStore(ofType: EncryptedStoreType, configurationName: nil, at: appSupportDirURL, options: containerOptions as? [AnyHashable : Any])
        }
        catch
        {
            print("WARNING!! : "+error.localizedDescription)
        }
        return container
    }()

РЕДАКТИРОВАТЬ: хотя он компилируется, я сталкиваюсь с этой ошибкой с этой реализацией:

2019-03-06 17:01:36.771430-0700 Yah-El[1060:1310006] [error] error: -addPersistentStoreWithType:EncryptedStore configuration:(null) URL:file:///var/mobile/Containers/Data/Application/AF6374B3-9127-4E2E-9CAF-D9C89D050D51/Documents/ options:{
    EncryptedStorePassphrase = someKey;
} ... returned error Error Domain=NSSQLiteErrorDomain Code=14 "(null)" UserInfo={EncryptedStoreErrorMessage=unable to open database file} with userInfo dictionary {
    EncryptedStoreErrorMessage = "unable to open database file";
}
CoreData: error: -addPersistentStoreWithType:EncryptedStore configuration:(null) URL:file:///var/mobile/Containers/Data/Application/AF6374B3-9127-4E2E-9CAF-D9C89D050D51/Documents/ options:{
    EncryptedStorePassphrase = someKey;
} ... returned error Error Domain=NSSQLiteErrorDomain Code=14 "(null)" UserInfo={EncryptedStoreErrorMessage=unable to open database file} with userInfo dictionary {
    EncryptedStoreErrorMessage = "unable to open database file";
}
WARNING!! : The operation couldn’t be completed. (NSSQLiteErrorDomain error 14.)

0 ответов

При втором подходе вы были довольно близки, но вместо того, чтобы обойти appSupportDirURL (папка!) в addPersistentStore(), передайте файл базы данных:

let storeURL = appSupportDirURL.appendingPathComponent("YourDatabaseName.sqlite")

let store = try container.persistentStoreCoordinator.addPersistentStore(ofType: EncryptedStoreType, configurationName: nil, at: storeURL, options: containerOptions as? [AnyHashable : Any])

Но я считаю, что вместо обработки путей удобнее просто задать persistentStoreDescriptions:

let container = NSPersistentContainer(name: "YourContainerName")
        
do {
    let options = [
       EncryptedStorePassphraseKey : "YourPassword"
    ]
            
    let description = try EncryptedStore.makeDescription(options: options, configuration: nil)
    container.persistentStoreDescriptions = [ description ]
}
catch {
    NSLog("Could not initialize encrypted database storage: " + error.localizedDescription)
}
        
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
    if let error = error as NSError? {
       fatalError("Unresolved error \(error), \(error.userInfo)")
    }
})
Другие вопросы по тегам