ios - 有时后台 Realm 会丢失所有数据库

标签 ios swift realm

我使用的是 Realm 2.1.1,并且从 0.98 版本开始使用。

有时发生的情况是,当用户进入后台时,经过 1 小时或更长时间后, Realm 数据库会丢失所有对象。

已经检查过了,我没有在后台执行任何保存或检索某些对象。

我在 didFinishLaunchingWithOptions 上执行了到应用程序组的迁移,因为我正在使用一个小部件,我认为这导致了问题,因为它尝试从另一个线程访问 Realm 。 Realm 数据库是加密的,所以我不知道是否可能是钥匙串(keychain)中的某些东西进入了后台。

这是我初始化 RealmDatabase 的代码:

class func migrateRealm() {
    let config = RLMRealmConfiguration.defaultConfiguration()
    config.schemaVersion = realmSchemeVersion()
    config.migrationBlock = {(migration:RLMMigration, oldSchemaVersion: UInt64) in }
    RLMRealmConfiguration.setDefaultConfiguration(config)

    //Cache original realm path (documents directory)

    guard let originalDefaultRealmPath = RealmEncrypted.realm().configuration.fileURL?.absoluteString else {
        return
    }

    //Generate new realm path based on app group
    let appGroupURL = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier("app")!
    let realmPath = appGroupURL.URLByAppendingPathComponent("default.realm")?.path ?? ""
    //Moves the realm to the new location if it hasn't been done previously

    if (NSFileManager.defaultManager().fileExistsAtPath(originalDefaultRealmPath) && !NSFileManager.defaultManager().fileExistsAtPath(realmPath)) {
        do {
            try NSFileManager.defaultManager().moveItemAtPath(originalDefaultRealmPath, toPath: realmPath)
            //Set the realm path to the new directory
            config.fileURL = NSURL(string: realmPath)
            RLMRealmConfiguration.setDefaultConfiguration(config)

            do {
                try NSFileManager.defaultManager().removeItemAtURL(NSURL(string: originalDefaultRealmPath)!)
            }
            catch let error as NSError {
                print("Ooops! Something went wrong deleting : \(error)")
            }
        }
        catch let error as NSError {
            print("Ooops! Something went wrong: \(error)")
        }
    }
    else {
        config.fileURL = NSURL(string: realmPath)
        RLMRealmConfiguration.setDefaultConfiguration(config)
    }
}

最佳答案

在代码级别,我可以看到的唯一可能导致问题的地方是您在内存中创建一个 Realm 实例,然后尝试在之后移动它。

执行此操作的特定行是 guard let originDefaultRealmPath = RealmEncrypted.realm().configuration.fileURL

Realm 在内部缓存 Realm 的副本,以便它们可以在后续调用中回收。因此,如果您在内存中创建引用,然后将物理文件移动到磁盘上,则会导致意外行为,甚至可能导致数据丢失。

最佳实践是尝试直接使用负责创建此 Realm 的 Configuration 对象。如果您绝对需要访问 Realm,然后想要在磁盘上移动文件,您可以将该代码封装在 @autoreleasepool 中,以保证 Realm 实例从内存中删除在移动文件之前。

就您可能需要考虑的其他潜在事项而言:您可能需要change your file access permissions以便在后台写入 Realm 文件。

此外,您可能是正确的,因为当应用程序处于后台时您也无法访问钥匙串(keychain)值。显然有another SO question that talks about this .

关于ios - 有时后台 Realm 会丢失所有数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41106520/

相关文章:

swift - 使用 CryptoSwift 从文件中获取哈希

android - 创建 360 度交互式产品预览

swift - API 违规 - 多次调用 -[XCTestExpectation fulfill]

html - UIMarkupTextPrintFormatter 创建具有自定义背景和透明 HTML 内容的 PDF

android - 为什么/何时使用 realm.beginTransaction?由于有executeTransaction和executeTransactionAsync

java - 1个项目中的多 Realm 数据库

java - 当应用程序未打开并且当我尝试在 Realm 中插入数据时,我收到错误 "Realm cannot be automatically updated on a thread > without a looper"?

html - 如何更改 WKWebView 文本颜色?

ios - IBOutlets 和 IBActions 没有出现在 main.storyboard 的 View Controller 中

ios - 给定一个 CIImage,将图像数据写入磁盘的最快方法是什么?