【问题标题】:How to update EncryptedCoreData implementation for Swift 4 app (NSSQLiteErrorDomain error 14)如何更新 Swift 4 应用程序的 EncryptedCoreData 实现(NSSQLiteErrorDomain 错误 14)
【发布时间】:2019-03-04 23:05:22
【问题描述】:

我正在重构一个订单处理应用程序以包含 CoreData,以便它可以缓存大量数据,并且其中一些数据包含一些我宁愿加密而不是加密的身份敏感内容。此应用程序将在一个成为黑客大目标的位置使用。所以我决定在我走得太远之前,我最好使用EncryptedCoreData 之类的东西来保护数据库。

事实证明,遵循 this 文章中的指示比作者暗示的要困难,至少对于像我这样的 CoreData 初学者而言。

我确实安装了 pod 并设置了一个桥接头,以便我可以在我的 Swift 项目中访问它,但不知道他引用的代码应该去哪里,或者使用什么 URL,等等。

对于类似问题here 的接受答案对我来说很有意义,因此我复制了它,但它没有针对 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.)

【问题讨论】:

    标签: core-data swift4 encrypted-core-data-sql


    【解决方案1】:

    使用第二种方法,您已经非常接近了,但不是将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)")
        }
    })
    

    【讨论】:

    • 哦,伙计,谢谢你的回答,但我决定重构整个应用程序,丢弃 CoreData,只使用加密的 SQLite 包并构建我自己的数据库管理器。事实证明,找出我自己的实现比尝试找出 CoreData 更容易。
    猜你喜欢
    • 2014-09-01
    • 1970-01-01
    • 2018-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多