2
votes

My iOS app is using Realm database I want to copy or move the current default.realm database file to the new directory (App Group location) so that I can share it with Today Extension widget.

I tried as this post says (How to transfer Realm database to appgroups)

The core code is

let fileManager = FileManager.default
let originalPath = Realm.Configuration.defaultConfiguration.fileURL!
let appGroupURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.myApp")!.appendingPathComponent("default.realm")
do{
    try fileManager.replaceItemAt(appGroupURL, withItemAt: originalPath)
}
catch{
    print("Error information: \(error)")
}

And I put this code inside Realm migration scope inside didFinishLaunchingWithOptions as below To give you clearer picture where I'm using this code.


func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    var config = Realm.Configuration(
        schemaVersion: 1,
        migrationBlock: { migration, oldSchemaVersion in
            if (oldSchemaVersion < 1) {
                let fileManager = FileManager.default
                let originalPath = Realm.Configuration.defaultConfiguration.fileURL!
                let appGroupURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.myApp")!.appendingPathComponent("default.realm")
                do{
                    try fileManager.replaceItemAt(appGroupURL, withItemAt: originalPath)
                }
                catch{
                    print("Error information: \(error)")
                }
            }
    }
    )
}


When I try this, my console says the file couldn't be saved.

Error Domain=NSCocoaErrorDomain Code=512 "The file “default.realm” couldn’t be saved in the folder “2EEADCEE-F9D9-44A8-BDED-B60A689656A2”." UserInfo={NSFileOriginalItemLocationKey=file:///Users/jm/Library/Developer/CoreSimulator/Devices/38334AE3-6648-402E-AC18-8252426002D6/data/Containers/Shared/AppGroup/2EEADCEE-F9D9-44A8-BDED-B60A689656A2/default.realm, ......

I heard copy / moving Realm database file should be done before opening the file, is this error related to that?

Thanks for your help and have a great day

1
Two things. 1) You can't alter, change or monkey with Realm in any way once your app 'talks' to it. So if there are any calls to realm (of any kind) that happen prior to didFinishLaunchingWithOptions then it won't work. 2) This may be a sandboxing issue, does your app have access to the folder being written to?Jay
Thanks @Jay I’m a beginner developer so I maybe wrong but if didFinishLaunchingWithOptions runs before viewDidLoad, I guess this is the first call to realm. For 2) I believe so as App Group folder is place for sharing data with today extension apps? Did I have to do additional work for getting access to this path? Sorry for being not so helpful to your questionsJM_Developer

1 Answers

3
votes

Thank you @Jay for commenting which helped my find a way.

As he mentioned moving Realm DB file should be done before we call anything related to the Realm.

Originally I had a code inside of Realm migration so that it will run only once when the schema version is older,

but I moved it outside, top of the didFinishLaunchingWithOptions so now it works moving Realm DB file to the different directory.

Hope this helps somebody who's struggling.


let fileManager = FileManager.default
let originalPath = Realm.Configuration.defaultConfiguration.fileURL!
let appGroupURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.myApp")!.appendingPathComponent("default.realm")
if fileManager.fileExists(atPath: originalPath.absoluteString) {
    do{
        try fileManager.replaceItemAt(appGroupURL, withItemAt: originalPath)
        print("Successfully replaced DB file")
    }
    catch{
        print("Error info: \(error)")
    }
} else {
    print("File is not exist on original path")
}


var config = Realm.Configuration(
)
config.fileURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.myApp")!.appendingPathComponent("default.realm")

// Tell Realm to use this new configuration object for the default Realm
Realm.Configuration.defaultConfiguration = config

// Now that we've told Realm how to handle the schema change, opening the file
// will automatically perform the migration
let realm = try! Realm()