- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试使用 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
, andThreadSafeReference
objects, and theRealm
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 访问器对象的引用(Realm
、Results
、ThreadSafeReference
或 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/
由于以下原因,我收到了 RLMException: Attempting to create an object of type 'Student' with an existing primary
在后台异步保存对象时,我得到RLMException: 'Can not add objects from a different Realm'。但是,如果删除异步代码,同样的保存工作正常。 此对象与
我有一个对象 NotSureItem,其中我有三个属性 title,其名称由 text 和 textDescription 重命名> 这是我后来添加的,还有一个 dateTime 属性。现在,当我要运
我正在尝试将 Realm 对象(事件)保存到 Realm 数据库,但是当我尝试将其崩溃时,指出: Terminating app due to uncaught exception 'RLMExcep
我目前正在编写一个程序,这将是我的专业“计算机科学”的最后一个项目。我正在制作的应用程序是用 Swift 编写的。它基本上是一个应用程序,允许编写和分类用户计划每天、每月或每年执行的任务。我刚刚陷入了
我一直在成功使用以下代码,突然,对于我的一个模型,Realm在commitWriteTransaction上抛出索引超出范围错误。 Realm对象已成功创建,并且仅在下面的最后一行显示错误,并且仅在我
我删除了 bd 中的 1 个对象 Realm 并取得了成功,但是当在 tableview 中滚动到之前占据该对象的位置时,应用程序损坏了。还要删除数组中的对象并重新加载 tableview 我不明白这
这个问题我查了相关文章。 Issue in adding data in Realm in iOS 似乎只发布了以前的帖子,人们没有向变量添加动态。那不是我的情况。我根本找不到任何其他原因会失败。 B
我认为我做对了。 let realm = try! Realm() do { try realm.write { realm.add(myObject) } } cat
我有一系列单独的 XCTest 单元测试,每个单元测试都运行一个 JSON 解析函数 - 作为解析的一部分,存在的 Realm 对象类的任何实例在它们被删除之前被删除根据正在处理的 JSON 重新创建
这不是重复问题,请继续阅读! 当我在 DispatchQueue 中使用我的 RealmBackend 单例时,我收到“'RLMException',原因:'从不正确的线程访问的 Realm '”错误
我有一个应用程序,在注销后,出于合规性原因,需要删除所有 Realm 数据并更改加密 key 。 这与RLMException "Realm at path ' ' already opened wi
我无法追踪其中一个错误的来源: *** 由于未捕获的异常“RLMException”而终止应用程序,原因:“此方法只能在从 RLMRealm 检索到的 RLMArray 实例上调用” 我知道我很可能在
我有一个主 Realm 对象: @interface MasterRealmObject : RLMObject @property (nonatomic, strong) RLMArray *ret
我正在 swift 中使用 Realm 创建一个要保存在用户设备上的喜爱产品列表。 简而言之,标签栏 Controller 中嵌入了 2 个 View Controller (A 和 B)。 View
这个问题在这里已经有了答案: RLMException, Migration is required for object type (8 个答案) 关闭 6 年前。
我有一个存储时间线的 Realm 模型(我正在制作视频编辑应用程序)并且它经常在访问它的 RMArray 属性时崩溃。该应用程序已经发布,我自己还没有体验过,但我的 crushlytics 经常通知我
我需要将我的个人模型写入 Realm 数据库。我一直不明白这是什么意思,因为我使用的是一个 Realm 实例,而且我认为我使用的是同一个线程。我错了吗?? func updatePerson(ps:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launc
我收到以下错误:“RLMException,原因:集合在枚举时发生了变异。” 当我尝试这样做时出现错误: let realm = Realm() let words = realm.objects(W
我是一名优秀的程序员,十分优秀!