首页 文章

Realm.io RealmSwift其他领域迁移

提问于
浏览
0

我需要为我的 Other Realm 进行迁移 .

我通过这种方法获得我的领域路径( AppDelegate ) . 如果用户之前登录,我将检索用户的领域,否则我将使用 Default Realm .

func getRealmPath() -> String {
    let preferences : NSUserDefaults = NSUserDefaults()
    let username = preferences.objectForKey(usernameKey) as! String?

    if username != nil {
        let realmName =  ("\(username!).realm")

        print("RealmName: \(realmName)", terminator: "")

        let documents = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
        return documents.stringByAppendingPathComponent(realmName)
    }else{
        return Realm.Configuration.defaultConfiguration.path!
    }  
}

我通过这种方法进行了迁移(在 AppDelegate:didFinishLaunchingWithOptions 中调用) .

func updateRealm(){

    let config = Realm.Configuration(path: getRealmPath(), schemaVersion: 2, migrationBlock: { (migration, oldSchemaVersion) -> Void in

        print("oldSchemaVersion \(oldSchemaVersion)") 

         migration.create("RLMStringTimestamp", value: ["pKey": NSUUID().UUIDString, "value": "", "updatedAt": NSDate(), "createdAt": NSDate(), "deletedAt": Date().getInitDate(), "updatedBy" : " ", "syncedAt": NSDate() ])           

        if oldSchemaVersion < 2  {

           //MIGRATION
           let firstNameTimeStamp =  RLMStringTimestamp(newValue: oldObject!["firstName"] as? String)
           migration.create("RLMStringTimestamp", value: firstNameTimeStamp)
           newObject!["firstName"] = firstNameTimeStamp

        }
      }

      Realm.Configuration.defaultConfiguration = config

      //EDIT 2 
      Realm.Configuration.defaultConfiguration.path = getRealmPath()

     //EDIT 1
     //<strike>let realm = try! Realm(path: getRealmPath())</strike>

     //EDIT 4 
     print(Realm.Configuration.defaultConfiguration)

     //EDIT 3
     let realm = try! Realm()
     }

对于我的RLMCustomer对象,我将var firstName:String =“”修改为var firstName:RLMStringTimeStamp!

即使我将schemaVersion更改为非常高的值,migrationBlock也没有得到调用 . 任何人都可以帮助我发现我错过了什么或做错了什么?

运行应用程序后,它与 bad excess, code = 257 崩溃

编辑1:

错误:'试试!'表达式意外地引发了错误:错误Domain = io.realm Code = 0“提供的架构版本0小于上次设置的版本1” . UserInfo = 0x170660c00 :file /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-700.0.59/src/swift/stdlib/public/ core / ErrorType.swift,第50行

它似乎正在读取错误的配置文件,我怀疑错误是由于Realm.Configuration.defaultConfiguration = config如何设置其他Realm的配置?

编辑2:

我使我的默认领域包含我的其他领域的名称和路径

编辑4:

似乎配置文件是正确的 . 如果在旧领域有客户记录,我可以毫无问题地运行应用程序 . 我可以从 oldObject["firstName"] 获取值

print(Realm.Configuration.defaultConfiguration)

Realm.Configuration {path = /var/mobile/Containers/Data/Application/8670C084-75E7-4955-89FB-137620C9B00D/Documents/perwyl.realm; inMemoryIdentifier =(null); encryptionKey =(null); readOnly = 0; schemaVersion = 2; migrationBlock = <NSMallocBlock:0x170451220>; dynamic = 0; customSchema =(null); } oldSchemaVersion 0

非常感谢!!!

编辑5:解决我的问题

如果我将StringTimestamp对象直接分配给newObject,我不确定为什么会崩溃 .

let firstName = (oldObject!["firstName"] as? String)!
let firstNameTimeStamp =  StringTimestamp(newValue: firstName)
let testName = migration.create("StringTimestamp",value:     firstNameTimeStamp)
newObject!["firstName"] = firstNameTimeStamp //Crashes
newObject!["firstName"] = testName //works

感谢大家的指导! :)

3 回答

  • 0

    为什么不让领域使用默认配置?由于您将默认配置中的路径设置为 getRealmPath() ,因此可以执行以下操作:

    let realm = try! Realm()
    

    通过使用 Realm(path: getRealmPath()) 实例化域,您将覆盖先前设置的 defaultConfiguration . 也就是说,领域的路径变为 getRealmPath() ,但是您在 config 中设置的所有其他属性都将丢失,而是使用默认值 . 这包括 schemaVersion = 0migrationBlock = nil .

    初始化程序(如 Realm(path:)Realm(configuration:) )的目的是允许您使用默认值以外的替代配置 . 如果你想要的是使用默认配置的修改版本,那么你需要在以下方面做一些事情:

    // Get a copy of the default configuration
    var otherConfig = Realm.Configuration.defaultConfiguration
    // Update the copy with what you need
    otherConfig.path = "/some/path/otherRealm.realm"
    // Use the updated configuration to instantiate a realm
    let otherRealm = try! Realm(configuration: otherConfig)
    

    调试领域配置问题的一种巧妙方法是在实例化领域之前设置断点或打印日志 . 运行以下代码可以让我知道要使用的默认配置是什么 .

    print(Realm.Configuration.defaultConfiguration))
    let realm = try! Realm()
    

    输出看起来像

    Realm.Configuration {
        path = /Users/<full-path-omitted>/edman.realm;
        schemaVersion = 2;
        migrationBlock = <__NSMallocBlock__: 0x7faee04ac590>;
        // other properties...
    }
    

    通过查看它我确定我的领域是用 edman.realmschemaVersion = 2 的路径实例化的,并且它具有非零 migrationBlock .

  • 0

    每当架构更新时,您必须在架构配置中将架构版本更新为更大的值 . 也就是说,在你的 updateRealm() 函数中

    let config = Realm.Configuration(
        path: getRealmPath(),
        schemaVersion: 3, // any value larger than previous version
        migrationBlock: { /* ... */}
    })
    
    Realm.Configuration.defaultConfiguration = config
    let realm = try! Realm()
    

    来自realm docs .

    您可以通过设置Realm.Configuration.schemaVersion和Realm.Configuration.migrationBlock来定义迁移和关联的模式版本 . 使用此配置创建Realm时,如果需要迁移,将应用迁移块将Realm更新为给定的架构版本 .

    您正确设置了迁移块,但未更新架构版本 . 这就是迁移块未被执行的原因,尽管它在您的配置中提供 .

    磁盘中的版本与配置中的版本之间的差异是触发 migrationBlock 的原因 .

  • 0

    Swift 3.0解决方案

    class func realmConfigs(_ realmName: String) -> RealmSwift.Realm.Configuration?{
        var config = Realm.Configuration()
        config.readOnly = true
        // Use the default directory, but replace the filename with the username
        let fileURLString = Bundle.main.path(forResource: realmName, ofType: "realm")
        guard fileURLString != nil else {
            return nil
        }
        config.fileURL = URL(string: fileURLString!)
        config.schemaVersion = UInt64(1.0)
        // Set this as the configuration used for the default Realm
    
        return config
    }
    

    并将像这样使用

    var realm : Realm?
        do{
    
            let config = realmConfigs("FILE_NAME")
            Realm.Configuration.defaultConfiguration = config!
            realm = try Realm(fileURL: realmURL)
        }
        catch {
            print("Opening realm file error: \(error)")
        }
    

相关问题