I need to do a migration for my Other Realm
.
I get my realm path via this method (AppDelegate
). If a user logged in before, i will retrieve the user's realm else i will just use the 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!
}
}
I did my migration via this method (called inside 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()
}
For my RLMCustomer Object, i modified
var firstName: String = ""
tovar firstName: RLMStringTimeStamp!
Even if i change the schemaVersion
to something very high, the migrationBlock
didn't get call. Can anyone help me spot what am i missing or doing wrong?
After running the app, it crashes with bad excess, code = 257
EDIT 1:
error: 'try!' expression unexpectedly raised an error: Error Domain=io.realm Code=0 "Provided schema version 0 is less than last set version 1." UserInfo=0x170660c00 {NSLocalizedDescription=Provided schema version 0 is less than last set version 1.}: file /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-700.0.59/src/swift/stdlib/public/core/ErrorType.swift, line 50
It seems to be reading the wrong configuration file and i suspect the error is due to Realm.Configuration.defaultConfiguration = config
How do i set the configuration for Other Realm
?
EDIT 2:
I make my
default realm
to contains the name and path of myother realm
EDIT 4:
It seems that the configuration file is correct. I am able to run the app without problem if there's no customer record from the old realm. It will only crash when there's customer record in the old realm. I can get the values from the 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
Much Thanks!!!
EDIT 5: Solution to my problem
I'm not sure why it crashes if i assign
StringTimestamp object
directly to 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
Thanks for everyone's guidelines! :)
Why not letting realm use the default configuration? Since you set the path in default configuration to getRealmPath()
, it should be ok to do just:
let realm = try! Realm()
By instantiating the realm with Realm(path: getRealmPath())
you are overriding the defaultConfiguration
you had previously set. That is, the path of the realm becomes getRealmPath()
, but all other properties you set in config
are lost, and default values are used instead. This includes schemaVersion = 0
and migrationBlock = nil
.
The intent of initializers like Realm(path:)
and Realm(configuration:)
is to allow you to use alternative configurations other than the default. If what you want is to use a modified version of the default configuration, then you would need to do something on the lines of:
// 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)
One neat way to debug realm configuration problems is by setting breakpoints or printing logs before instantiating the realm. Running the following code lets me know what is the default configuration about to be used.
print(Realm.Configuration.defaultConfiguration))
let realm = try! Realm()
The output looks something like
Realm.Configuration {
path = /Users/<full-path-omitted>/edman.realm;
schemaVersion = 2;
migrationBlock = <__NSMallocBlock__: 0x7faee04ac590>;
// other properties...
}
By looking at it I'm sure my realm was instantiated with the path for edman.realm
, schemaVersion = 2
, and it has non-nil migrationBlock
.