9

I'm pretty new to ios development.

I follow this migration example to use pre-populated database and change the code a little bit

here is the final code I use on AppDelegate -> func application

    let defaultPath = Realm.Configuration.defaultConfiguration.path!
    let path = NSBundle.mainBundle().pathForResource("default", ofType: "realm")

    if let bundledPath = path {

        print("use pre-populated database")
        do {
            try NSFileManager.defaultManager().removeItemAtPath(defaultPath)
            try NSFileManager.defaultManager().copyItemAtPath(bundledPath, toPath: defaultPath)

        } catch {
            print("remove")
            print(error)
        }
    }

I'm testing this in a real device.

It works but according to the code logic, it'll always be reset to the pre-populated database. This is verified: the data is reset after app restart.

I tried moveItemAtPath instead of copyItemAtPath. permission error

I tried to delete the pre-populated database file after copy. permission error

I tried to use the pre-populated database file as the realm default configuration path. error occurs too.

Jesse
  • 231
  • 7
  • 17

3 Answers3

10

In Swift 3.0, try this:

    let bundlePath = Bundle.main.path(forResource: "default", ofType: "realm")
    let destPath = Realm.Configuration.defaultConfiguration.fileURL?.path
    let fileManager = FileManager.default

    if fileManager.fileExists(atPath: destPath!) {
        //File exist, do nothing
        //print(fileManager.fileExists(atPath: destPath!))
    } else {
        do {
            //Copy file from bundle to Realm default path
            try fileManager.copyItem(atPath: bundlePath!, toPath: destPath!)
        } catch {
            print("\n",error)
        }
    }
Luan Vo
  • 121
  • 1
  • 5
3

Yeah, your logic is correct. Every time this code gets executed, the default Realm file in the Documents directory is deleted and replaced with the static copy that came with the app bundle. This is done by design in the Realm sample code in order to demonstrate the migration process each time the app is launched.

If you only want that to happen one time, the easiest way to do it would be to check beforehand to see if a Realm file already exists at the default path, and then perform the copy only when it isn't already there. :)

let alreadyExists = NSFileManager.defaultManager().fileExistsAtPath(defaultPath)

if alreadyExists == false && let bundledPath = path {
    print("use pre-populated database")
    do {
        try NSFileManager.defaultManager().removeItemAtPath(defaultPath)
        try NSFileManager.defaultManager().copyItemAtPath(bundledPath, toPath: defaultPath)

    } catch {
        print("remove")
        print(error)
    }
}
TiM
  • 15,812
  • 4
  • 51
  • 79
  • oh, yep, this would be a way. btw, it is `fileExistsAtPath` – Jesse Apr 16 '16 at 01:31
  • @TiM why `file exists` always returns true? – aaisataev Apr 23 '17 at 19:34
  • @aaisataev Once the file is created, it's not necessary to run the same replacement code again. So it makes sense it would always return `true` after the first time. :) – TiM Apr 23 '17 at 19:40
  • @TiM it returns true even after resetting contents and settings. So I can't copy my realm file. But even after hardly copy this file `let realm = try! Realm()` returns empty list... – aaisataev Apr 23 '17 at 19:43
  • Calling `let realm = try! Realm()` will create a new, empty Realm file on disk when you call it. If you're checking the file exists after calling `try! Realm()`, it'll always return true. – TiM Apr 24 '17 at 00:24
0

try this

    let realm_db_path     = Realm.Configuration.defaultConfiguration.fileURL!
    let bundle_realm_path = Bundle.main.url(forResource: "default", withExtension: "realm")!

    if !FileManager.default.fileExists(atPath: realm_db_path.absoluteString){
        do {

            try FileManager.default.copyItem(at: bundle_realm_path, to: realm_db_path)

        }catch let error {

            NSLog(error as! String)

        }