如何保证领域迁移在访问领域之前完成?迁移领域数据库并开始读/写领域似乎存在竞争条件。这是我的问题:
目前,当用户启动应用程序时,我正在使用迁移关闭设置领域配置。一旦使用RLMRealmConfiguration.setDefaultConfiguration(config)设置了领域配置,我就设置了RootViewController并开始访问领域数据。
但是,当需要迁移时,有时会在迁移完成之前访问域 - 导致崩溃(RLMException:对象已被删除或无效)。如果迁移是一个没有回调的异步任务,我们怎样才能保证它在访问领域之前完成?
这是我的领域配置代码:
class func SetRealmConfigurationForUser(userId: String) {
let config = RLMRealmConfiguration.defaultConfiguration()
// migration setup
config.schemaVersion = 10
config.migrationBlock = { migration, oldSchemaVersion in
if oldSchemaVersion < 2 {
migration.enumerateObjects(ContactUser.className()) { oldObject, newObject in
// Change primary key from PhoneNumber to Phone_BaseId_Key
let phone = oldObject?["PhoneNumber"]
let baseId = oldObject?["BaseId"]
newObject?["Phone_BaseId_Key"] = String(phone) + "_" + String(baseId)
}
}
if oldSchemaVersion < 3 {
migration.enumerateObjects(DigitsContact.className()) { oldObject, newObject in
newObject?["ExternalId"] = ""
}
}
if oldSchemaVersion < 9 {
migration.deleteDataForClassName(DigitsContact.className())
migration.deleteDataForClassName(Address.className())
migration.deleteDataForClassName(Email.className())
migration.deleteDataForClassName(PhoneNumber.className())
}
}
// Use default directory, but replace filename with the userId
config.path = (((config.path! as NSString).stringByDeletingLastPathComponent as NSString)
.stringByAppendingPathComponent(userId) as NSString)
.stringByAppendingPathExtension("realm")
RLMRealmConfiguration.setDefaultConfiguration(config)
答案 0 :(得分:1)
根据Realm's Migrations docs,只有在使用设置了架构版本和迁移块的配置打开Realm
时才会应用迁移:
使用此配置创建Realm时,如果需要迁移,将应用迁移块将Realm更新为给定的架构版本。
因此,如果您异步调用SetRealmConfigurationForUser
,任何并发Realm访问都将使用以前的默认配置,而不会看到您在此过程中的迁移块定义。
执行迁移始终是同步发生的,可以通过在其配置中创建具有迁移块的Realm或通过调用RLMRealm.migrateRealm(_:)
显式地隐式实现。
迁移完成时将阻止所有其他Realm访问(读取和写入)。所以只要迁移块和&amp;在任何Realm初始化之前设置配置,应该没有竞争条件。
PS:oldSchema < 3
您在迁移阻止中浪费了大量工作,因为您将所有DigitsContact.ExternalId
属性设置为""
,只是为了DigitsContact
然后删除所有oldSchemaVersion < 3
个对象。只需删除sig
条件及其内容就会产生相同的结果。