简体   繁体   English

如何更新 Swift 4 应用程序的 EncryptedCoreData 实现(NSSQLiteErrorDomain 错误 14)

[英]How to update EncryptedCoreData implementation for Swift 4 app (NSSQLiteErrorDomain error 14)

I'm refactoring an order processing app to include CoreData so it can cache large amounts of data, and some of the data includes some identity sensitive stuff I'd rather encrypt than not.我正在重构一个订单处理应用程序以包含 CoreData,以便它可以缓存大量数据,并且其中一些数据包含一些我宁愿加密也不愿加密的身份敏感内容。 This app will be used in a location that is a big target for hackers.此应用程序将用于黑客的主要目标位置。 So I decided before I get too far, I'd better use something like EncryptedCoreData to secure the database.所以我决定在我走得太远之前,我最好使用诸如EncryptedCoreData 之类的东西来保护数据库。

Following directions from this article proved to be more difficult than the author implied, at least for a beginner to CoreData such as myself.从以下几个方向文章被证明是更困难比笔者暗示,至少对于初学者CoreData像我这样的。

I did get the pod installed and set up a bridging header so I can access it in my Swift project, but have no idea where the code he is referencing should go, or what URL to use, etc.我确实安装了 pod 并设置了一个桥接头,这样我就可以在我的 Swift 项目中访问它,但不知道他引用的代码应该放在哪里,或者使用什么 URL,等等。

The accepted answer for a similar question here makes enough sense to me that I reproduced it, but it's not updated for Swift 4 and I'm getting two errors: 此处类似问题的公认答案对我来说很有意义,我复制了它,但它没有针对 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
    }()

I can resolve "Error: Use of unresolved identifier 'EncryptedStoreFileManager'" easily enough by commenting out this portion of the code - I suspect it is no longer necessary.通过注释掉这部分代码,我可以很容易地解决“错误:使用未解析的标识符 'EncryptedStoreFileManager'”——我怀疑它不再需要了。 The second error is harder though - EncryptedStoreDescription is not a class that I can see, so I can't access an initializer, and EncryptedStore no longer has a method for creating a description.不过,第二个错误更难 - EncryptedStoreDescription 不是我可以看到的类,因此我无法访问初始化程序,并且 EncryptedStore 不再具有创建描述的方法。

What am I missing?我错过了什么?

EDIT: The following attempted solution did not work.编辑:以下尝试的解决方案不起作用。

I figured out the following UNTESTED implementation, I'm hoping I'll have some success.我想出了以下未经测试的实现,我希望我能取得一些成功。 Will update if I run into trouble.如果我遇到麻烦会更新。

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
    }()

EDIT: Although it compiles, I run into this error with this implementation:编辑:虽然它可以编译,但我在这个实现中遇到了这个错误:

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.)

With your second approach you were quite close, but instead of passing appSupportDirURL (a folder!) to addPersistentStore() , pass a database file:使用第二种方法,您非常接近,但不是将appSupportDirURL (一个文件夹!)传递给addPersistentStore()addPersistentStore()传递一个数据库文件:

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

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

But instead of handling paths I think it's more convenient to just set persistentStoreDescriptions :但不是处理路径,我认为设置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)")
    }
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 persistentstorecoordinator coredata错误:NSSQLiteErrorDomain = 522 - persistentstorecoordinator coredata error:NSSQLiteErrorDomain = 522 尝试访问sqlite文件时,NSPersistentStoreCoordinator引发错误NSSQLiteErrorDomain = 26 - NSPersistentStoreCoordinator raises error NSSQLiteErrorDomain=26 when trying to access sqlite file UITabBarController应用(Swift 1.2)中用于iCloud同步的核心数据堆栈实现 - Core Data stack implementation for iCloud sync in a UITabBarController app (Swift 1.2) 无法使用EncryptedCoreData检索以前的数据 - Unable to retrieve previous data with EncryptedCoreData 应用程序委托的Swift Xcode 7错误 - Swift Xcode 7 error with app delegate Swift:如何更新可变形对象 - Swift: How to update transformable objects CoreData Swift:崩溃:SQLite错误代码:14,“无法打开数据库文件” - CoreData Swift : Crash : SQLite error code:14, 'unable to open database file' iOS 14 Beta - Swift UI 中的核心数据错误:任何 model 中没有 NSEntityDescriptions 声明 NSManagedObject 子类 - iOS 14 Beta - Core Data in Swift UI Error: No NSEntityDescriptions in any model claim the NSManagedObject subclass 如何在Swift中更新TableView数据 - How to update TableView data in Swift 具有EncryptedCoreData的体系结构i386的未定义符号 - Undefined symbols for architecture i386 with EncryptedCoreData
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM