我在使用Realm时遇到麻烦,给我这样的错误:我的对象不存在具有给定名称的属性。但我知道它确实存在。
我尝试关注https://realm.io/docs/swift/latest/#updating-values上的文档。我已经搜索了所有可以想到的东西,以在此处和其他地方找到适用的解决方案,但没有找到任何可行的方法。
我以前执行过一个简单的迁移,只是将属性添加到同一Realm中的另一个对象。我只是将迁移块留空,并且工作正常。该迁移应该将我的架构从0设置为1。如果我在将我的架构设置为1的情况下运行它并检查版本是否小于2,它告诉我必须运行迁移才能添加这些属性。迁移正在运行。每当执行时,我都有一个打印语句。如果将模式设置为2,但仍检查是否小于2,除非取消注释旧属性,否则会收到错误的旧属性名称错误。然后我仍然会收到新属性的错误。
这是我的Realm对象。注释掉的行是我要从中迁移的旧属性。我要迁移到Int值。
@objcMembers class Options: Object {
// dynamic var morningStartTime: Date?
// dynamic var afternoonStartTime: Date?
// dynamic var eveningStartTime: Date?
// dynamic var nightStartTime: Date?
dynamic var morningHour: Int = 7
dynamic var morningMinute: Int = 0
dynamic var afternoonHour: Int = 12
dynamic var afternoonMinute: Int = 0
dynamic var eveningHour: Int = 17
dynamic var eveningMinute: Int = 0
dynamic var nightHour: Int = 21
dynamic var nightMinute: Int = 0
dynamic var morningNotificationsOn: Bool = true
dynamic var afternoonNotificationsOn: Bool = true
dynamic var eveningNotificationsOn: Bool = true
dynamic var nightNotificationsOn: Bool = true
dynamic var firstItemAdded: Bool = false
dynamic var smartSnooze: Bool = false
dynamic var optionsKey = UUID().uuidString
override static func primaryKey() -> String? {
return "optionsKey"
}
}
我的迁移阻止:
let config = Realm.Configuration(
// Set the new schema version. This must be greater than the previously used
// version (if you've never set a schema version before, the version is 0).
schemaVersion: 2,
// Set the block which will be called automatically when opening a Realm with
// a schema version lower than the one set above
migrationBlock: { migration, oldSchemaVersion in
// We haven’t migrated anything yet, so oldSchemaVersion == 0
if (oldSchemaVersion < 2) {
migration.enumerateObjects(ofType: Options.className(), { (newObject, oldObject) in
let morningStartTime = oldObject!["morningStartTime"] as! Date?
let afternoonStartTime = oldObject!["afternoonStartTime"] as! Date?
let eveningStartTime = oldObject!["eveningStartTime"] as! Date?
let nightStartTime = oldObject!["nightStartTime"] as! Date?
newObject!["morningHour"] = self.getHour(date: morningStartTime)
newObject!["morningMinute"] = self.getMinute(date: morningStartTime)
newObject!["afternoonHour"] = self.getHour(date: afternoonStartTime)
newObject!["afternoonMinute"] = self.getMinute(date: afternoonStartTime)
newObject!["eveningHour"] = self.getHour(date: eveningStartTime)
newObject!["eveningMinute"] = self.getMinute(date: eveningStartTime)
newObject!["nightHour"] = self.getHour(date: nightStartTime)
newObject!["nightMinute"] = self.getMinute(date: nightStartTime)
})
}
})
getHour
和getMinute
只是我编写的从Int
返回一个小时或分钟的Date
的函数。如果相关,请在这里。
func getHour(date: Date?) -> Int {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH"
let hour = dateFormatter.string(from: date!)
return Int(hour)!
}
func getMinute(date: Date?) -> Int {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "mm"
let minutes = dateFormatter.string(from: date!)
return Int(minutes)!
}
答案 0 :(得分:0)
我知道这不是做到这一点的方法,但是我通过对迁移块采用稍微更手动的方法来使其工作。我取消了Options
对象中的旧属性的注释,并将迁移函数更改为以下内容:
func migrateRealm() {
let configCheck = Realm.Configuration();
do {
let fileUrlIs = try schemaVersionAtURL(configCheck.fileURL!)
print("schema version \(fileUrlIs)")
} catch {
print(error)
}
print("performing realm migration")
let config = Realm.Configuration(
// Set the new schema version. This must be greater than the previously used
// version (if you've never set a schema version before, the version is 0).
schemaVersion: 2,
// Set the block which will be called automatically when opening a Realm with
// a schema version lower than the one set above
migrationBlock: { migration, oldSchemaVersion in
print("oldSchemaVersion: \(oldSchemaVersion)")
if (oldSchemaVersion < 2) {
print("Migration block running")
DispatchQueue(label: self.realmDispatchQueueLabel).async {
autoreleasepool {
let realm = try! Realm()
let options = realm.object(ofType: Options.self, forPrimaryKey: self.optionsKey)
do {
try realm.write {
if let morningTime = options?.morningStartTime {
options?.morningHour = self.getHour(date: morningTime)
options?.morningMinute = self.getMinute(date: morningTime)
}
if let afternoonTime = options?.afternoonStartTime {
options?.afternoonHour = self.getHour(date: afternoonTime)
options?.afternoonMinute = self.getMinute(date: afternoonTime)
}
if let eveningTime = options?.eveningStartTime {
options?.eveningHour = self.getHour(date: eveningTime)
options?.eveningMinute = self.getMinute(date: eveningTime)
}
if let nightTime = options?.nightStartTime {
options?.nightHour = self.getHour(date: nightTime)
options?.nightMinute = self.getMinute(date: nightTime)
}
}
} catch {
print("Error with migration")
}
}
}
}
})
// Tell Realm to use this new configuration object for the default Realm
Realm.Configuration.defaultConfiguration = config
// Now that we've told Realm how to handle the schema change, opening the file
// will automatically perform the migration
_ = try! Realm()
}
这仅在我将它异步地在另一个线程上排队时才有效。我想如果这些数据对于我的初始视图控制器来说是必需的,那么它很可能创建了导致应用崩溃的竞争状态。幸运的是,这仅出现在辅助视图中,因此在需要这些值之前有时间来完成。我想我将来的应用程序版本中必须使用更新的Realm架构删除未使用的属性。