Realm.io RealmSwift Миграция в другие сферы
Мне нужно сделать миграцию для моего 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 {NSLocalizedDescription= Предоставленная версия схемы 0 меньше, чем последняя установленная версия 1.}: файл /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-700.0.59/src/swift/stdlib/public/core/ErrorType.swift, строка 50
Кажется, что он читает неправильный файл конфигурации, и я подозреваю, что ошибка связана с Realm.Configuration.defaultConfiguration = config
Как мне установить конфигурацию для Other Realm
?
РЕДАКТИРОВАТЬ 2:
Я делаю мой
default realm
содержит имя и путь моегоother realm
РЕДАКТИРОВАТЬ 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 = (ноль); readOnly = 0; schemaVersion = 2; igrationBlock = < NSMallocBlock: 0x170451220>; динамический = 0; customSchema = (ноль); } oldSchemaVersion 0
Большое спасибо!!!
РЕДАКТИРОВАТЬ 5: Решение моей проблемы
Я не уверен, почему происходит сбой, если я назначаю
StringTimestamp object
непосредственно к 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 ответа
Почему бы не позволить области использовать конфигурацию по умолчанию? Поскольку вы устанавливаете путь в конфигурации по умолчанию getRealmPath()
, это должно быть в порядке, чтобы сделать только:
let realm = try! Realm()
Создавая царство с Realm(path: getRealmPath())
вы переопределяете defaultConfiguration
Вы ранее установили. То есть путь царства становится getRealmPath()
, но все остальные свойства, которые вы устанавливаете в config
теряются, и вместо них используются значения по умолчанию. Это включает schemaVersion = 0
а также migrationBlock = 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.realm
, schemaVersion = 2
и имеет не ноль migrationBlock
,
Вы должны обновить версию схемы до большего значения в конфигурации вашей области всякий раз, когда ваша схема обновляется. То есть в вашем 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.Configuration.schemaVersion
а такжеRealm.Configuration.migrationBlock
,При создании области с этой конфигурацией будет применен блок миграции, чтобы обновить область до указанной версии схемы, если требуется миграция.
Вы правильно установили блок миграции, но не обновили версию схемы. Вот почему блок миграции не выполняется, хотя он предусмотрен в вашей конфигурации.
Разница между версией на диске и версией в вашей конфигурации заключается в том, что вызывает migrationBlock
,
Решение 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)")
}