0

Im using Realm 2.1.1, and been using since the version 0.98.

What is happening is sometimes when the user enter background, after sometime like 1 hour or more, the Realm Database loses all its objects.

Already check it, and im not permforming any saving or retrieve some objects on the background.

I perform a migration to app group on the didFinishLaunchingWithOptions, because i was using an Widget, that i think that was causing the problem, since it try to access realm from another thread. The realm database is encrypted, so i don't know if maybe its something from the keychain entering the background.

Heres my code to initialize the 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)
    }
}
TiM
  • 15,812
  • 4
  • 51
  • 79
Vinícius Albino
  • 527
  • 1
  • 7
  • 23

1 Answers1

0

On the code level, the only thing that I can see there that may be potentially causing issues is that you're creating a Realm instance in memory, and then attempting to move it afterwards.

The particular line that's doing this is guard let originalDefaultRealmPath = RealmEncrypted.realm().configuration.fileURL.

Realm internally caches copies of Realm so that they can be recycled on subsequent calls. As such, if you create a reference in memory, and then move the physical file on disk, that will lead to unexpected behavior, and even potentially data loss.

The best practice is to try and work directly with the Configuration object responsible for the creation of this Realm. If you absolutely need to access Realm and then want to move the file around on disk, you can encapsulate that code inside an @autoreleasepool to guarantee the Realm instance is removed from memory before you move the file.

In terms of other potential things you might need to consider: you may need to change your file access permissions in order to write to Realm files while in the background.

Additionally, you may be correct in that you're not able to access keychain values while the app is backgrounded as well. There's apparently another SO question that talks about this.

Community
  • 1
  • 1
TiM
  • 15,812
  • 4
  • 51
  • 79