gpt4 book ai didi

ios - writeCopy 后出现 RLMException "Realm at path ' ' already opened with different encryption key"(toFile :, 加密 key :)

转载 作者:行者123 更新时间:2023-11-29 00:13:36 27 4
gpt4 key购买 nike


我正在尝试使用 writeCopy(toFile:, encryptionKey:) 更改我的 Realm 数据库的加密 key ,如下所示:

public static func updateEncryption(forNewKey newKey: String, withOldKey oldKey: String, completion: (() -> Void)) {

let defaultURL = Backup.realmContainerURL
let defaultParentURL = defaultURL.deletingLastPathComponent()
let compactedURL = defaultParentURL.appendingPathComponent("default-compact.realm")

let oldKeyData = oldKey.pbkdf2SHA256(keyByteCount: 64)
let newKeyData = newKey.pbkdf2SHA256(keyByteCount: 64)

let oldEncryptionConfig = Realm.Configuration(fileURL: Backup.realmContainerURL, encryptionKey: oldKeyData)

autoreleasepool {
do {
let oldRealm = try Realm(configuration: oldEncryptionConfig)
try oldRealm.writeCopy(toFile: compactedURL, encryptionKey: newKeyData)
oldRealm.invalidate()
try FileManager.default.removeItem(at: defaultURL)
try FileManager.default.moveItem(at: compactedURL, to: defaultURL)
completion()
} catch {
fatalError(error.localizedDescription)
}
}
}

之后,我使用以下方法在我的应用中重新加载数据:

public static func loadAll(withEncryptionKey encryptionKey: String) -> [Backup] {
do {
let key = encryptionKey.pbkdf2SHA256(keyByteCount: 64)
let encryptionConfig = Realm.Configuration(fileURL: Backup.realmContainerURL, encryptionKey: key)
let realm = try Realm(configuration: encryptionConfig)
let allObjects = realm.objects(Backup.self).sorted(byKeyPath: "date", ascending: false)
return allObjects.map({ $0 })
} catch {
fatalError(error.localizedDescription)
}
}

所以我使用带有新 key 的 loadAll(withEncryptionKey:) 函数,但是 let realm = try Realm(configuration: encryptionConfig) 应用程序在 RLMRealm 中崩溃.mm 文件,第 347 行:@throw RLMException(@"Realm at path '%s' already opened with different encryption key", config.path.c_str()); with console log libc++abi.dylib: 以 NSException 类型的未捕获异常终止
所以看起来 writeCopy(toFile:, encryptionKey:) 没有改变 encryptionKey,或者 Realm 仍然看到旧的 .realm 文件。但有趣的是,在重新打开我的应用程序后,loadAll(withEncryptionKey:) 使用新的加密 key 加载数据没有任何问题。
如何解决这个问题呢?如何更改加密 key 并仍然可以使用应用程序?
非常感谢您的帮助。

最佳答案

这取决于您在何处调用 loadAll() 方法。也许您正在调用completion(),对吗?如果是这样,此时对旧 Realm 的引用尚未发布,并且仍保持开放状态。

就像从磁盘删除/替换 Realm 文件一样,只有当您的应用程序当前没有打开 Realm 文件时,替换磁盘上的 Realm 文件才是安全的。

摘自 Realm 的文档 Deleting Realm files :

Because Realm avoids copying data into memory except when absolutely required, all objects managed by a Realm contain references to the file on disk, and must be deallocated before the file can be safely deleted. This includes all objects read from (or added to) the Realm, all List, Results, and ThreadSafeReference objects, and the Realm itself.

In practice, this means that deleting a Realm file should be done either on application startup before you have opened the Realm, or after only opening the Realm within an explicit autorelease pool, which ensures that all of the Realm objects will have been deallocated.

原因是 Realm 维护打开文件的内存缓存,因此尝试打开已打开的文件将导致返回对已打开文件的引用。此打开的文件将继续引用磁盘上的原始文件,即使它已被替换。确保对 Realm 访问器对象的所有引用都已清理意味着 Realm 将不会返回现有的打开文件,而是从磁盘打开该文件。

换句话说,您必须确保没有对 Realm 访问器对象的引用(RealmResultsThreadSafeReference Object 实例)在您尝试替换 Realm 文件时。您还必须确保您拥有的任何引用都已被释放。

如果此时没有其他对 Realm 和 Realm 对象的引用,它将通过在自动释放 block 外部打开来成功,如下所示。

autoreleasepool {
do {
let oldRealm = try Realm(configuration: oldEncryptionConfig)
try oldRealm.writeCopy(toFile: compactedURL, encryptionKey: newKeyData)
oldRealm.invalidate()
try FileManager.default.removeItem(at: defaultURL)
try FileManager.default.moveItem(at: compactedURL, to: defaultURL)
} catch {
fatalError(error.localizedDescription)
}
}

loadAll(withEncryptionKey: ...)

另一种可能更易于管理的方法是在尝试重新打开恢复的文件时使用不同的路径。由于您正在访问磁盘上的不同路径,因此您一定会打开新文件。您仍然需要确保没有对 Realm 的访问器对象的引用,否则您将得到新旧数据的奇怪混合,但确保访问器对象被释放并不那么重要。

关于ios - writeCopy 后出现 RLMException "Realm at path ' ' already opened with different encryption key"(toFile :, 加密 key :),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45780841/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com