如何使用领域通知来检测嵌套领域对象的变化
How to use realm notifications to detect changes in nested realm objects
我正在尝试为 ios 构建一个应用程序来显示各种节日的日常节目。在此应用程序中,我希望每次组成节日节目的事件之一是 "added"、"modified" 或 "deleted" 时通知用户。
对于数据库,我使用的是领域云服务。
我的数据库结构如下:
我有一个名为 "Festival" 的 Realm 对象。在这里面我有一个 "DailyProgram" 对象的列表,在每个 "DailyProgram" 里面我有一个 "Event" 的列表。
我在下面提供了这些对象的片段。
当应用程序访问 Realm Cloud 时,它会下载一个包含所有不同节日的数组。
我想使用领域内置的通知系统来检测 "Event" 对象的变化。
我试图在这个节日数组上实现一个收集通知,但是当我在一个事件中对数据库进行更改时,收集通知只是 returns 与节日对应的数组索引变化发生。我想获得有关发生更改的特定事件以及更改内容的信息。
class Festival: Object {
@objc dynamic var festivalId: String = UUID().uuidString
@objc dynamic var name: String = ""
@objc dynamic var town: String = ""
@objc dynamic var initialDate: Date = Date()
@objc dynamic var finalDate: Date = Date()
let program = List<DailyProgram>()
override static func primaryKey() -> String? {
return "festivalId"
}
}
class DailyProgram: Object{
@objc dynamic var day: Date = Date()
let events = List<Event>()
}
class Event: Object {
@objc dynamic var name: String = ""
@objc dynamic var local: String = ""
@objc dynamic var time: Date = Date()
}
我很清楚 Realm 中对象通知的存在。我认为这些可能是我的问题的解决方案。我知道如何在单个对象上实现对象通知。但是,我不知道如何在嵌套对象的情况下实现这些类型的通知。
简答:
在事件与其所属的节日之间创建反向关系。然后根据属于特定节日的事件获得结果并观察它们。然后,当为该节日添加、修改或删除任何活动时,您将收到通知。
基于长代码的答案。从修改您的领域对象开始(我去掉了属性以缩短代码)
class Festival: Object {
@objc dynamic var festivalId: String = UUID().uuidString
@objc dynamic var name: String = ""
let program = List<DailyProgram>()
override static func primaryKey() -> String? {
return "festivalId"
}
}
class DailyProgram: Object {
@objc dynamic var day = ""
@objc dynamic var festival: Festival! //add this
let events = List<Event>()
}
class Event: Object {
@objc dynamic var daily_program: DailyProgram!
@objc dynamic var festival: Festival! //add this
@objc dynamic var name: String = ""
}
然后创建确保添加反向关系的对象。注意 var 命名,f0 = Fest 0,f1 = Fest 1,然后 dp = DailyProgram 和 e = Event。这样做是为了更容易看到层次结构。
let f0 = Festival()
f0.name = "Fest 0"
let f0dp0 = DailyProgram()
f0dp0.day = "Monday"
f0dp0.festival = f0
let f0dp0e0 = Event()
f0dp0e0.name = "Morning event"
f0dp0e0.daily_program = f0dp0
f0dp0e0.festival = f0
let f0dp0e1 = Event()
f0dp0e1.name = "Afternoon event"
f0dp0e1.daily_program = f0dp0
f0dp0e1.festival = f0
let f1 = Festival()
f1.name = "Fest 1"
let f1dp0 = DailyProgram()
f1dp0.day = "Monday"
f1dp0.festival = f1
let f1dp0e0 = Event()
f1dp0e0.name = "Evening event"
f1dp0e0.daily_program = f1dp0
f1dp0e0.festival = f1
let f1dp0e1 = Event()
f1dp0e1.name = "Midnight event"
f1dp0e1.daily_program = f1dp0
f1dp0e1.festival = f1
上面创建了两个节日,每个节日都有一个周一的每日节目,然后每个周一的节目都有两个活动。
然后我们加载我们的结果并添加一个观察者。在这种情况下,我们对 Fest 1 活动感兴趣。
var eventResults: Results<Event>? = nil
var eventNotificationToken: NotificationToken? = nil
func loadAndObserveFestivalEvents() {
if let realm = gGetRealm() {
self.eventResults = realm.objects(Event.self).filter("festival.name == %@", "Fest 1")
self.observeEvents()
}
}
func observeEvents() {
self.eventNotificationToken = self.eventResults!.observe { (changes: RealmCollectionChange) in
switch changes {
case .initial:
print("initial event load complete")
if let results = self.eventResults { //just shows events are loaded
for e in results {
let d = e.daily_program.day
let f = e.festival.name
print(f, d, e.name)
}
}
break
case .update(_, let deletions, let insertions, let modifications):
print(" handle event delete, insert or mod")
if let results = self.eventResults { //shows the list including the newly added event
for e in results {
let d = e.daily_program.day
let f = e.festival.name
print(f, d, e.name)
}
}
break
case .error(let error):
fatalError("\(error)")
break
}
}
}
此时我们已准备好向 Fest 1 的星期一活动添加一个活动,然后收到添加该活动的通知。
func addEvent() {
if let realm = gGetRealm() {
let dp = realm.objects(DailyProgram.self).filter("festival.name == %@ && day == %@", "Fest 1", "Monday")
if let daily = dp.first {
let eventToAdd = Event()
eventToAdd.daily_program = daily
eventToAdd.festival = daily.festival
eventToAdd.name = "Super Duper Event"
try! realm.write {
daily.events.append(eventToAdd)
}
}
}
}
代码的最后一部分创建一个结果对象,其中填充了 Fest 1,星期一的 DailyProgram。
然后我创建一个新事件,确保我 link 将其返回到 Fest 1 音乐节,然后将其添加到 DailyPrograms 事件列表中。
此代码可以大大缩短并利用 LinkingObject 自动创建 link 返回。然而,在这种情况下,一个事件将永远只属于一个 DailyProgram 和 Festival,所以它并不是真正需要的。
注意gGetRealm
是我用来连接realm的单例。
我正在尝试为 ios 构建一个应用程序来显示各种节日的日常节目。在此应用程序中,我希望每次组成节日节目的事件之一是 "added"、"modified" 或 "deleted" 时通知用户。
对于数据库,我使用的是领域云服务。 我的数据库结构如下: 我有一个名为 "Festival" 的 Realm 对象。在这里面我有一个 "DailyProgram" 对象的列表,在每个 "DailyProgram" 里面我有一个 "Event" 的列表。 我在下面提供了这些对象的片段。
当应用程序访问 Realm Cloud 时,它会下载一个包含所有不同节日的数组。
我想使用领域内置的通知系统来检测 "Event" 对象的变化。
我试图在这个节日数组上实现一个收集通知,但是当我在一个事件中对数据库进行更改时,收集通知只是 returns 与节日对应的数组索引变化发生。我想获得有关发生更改的特定事件以及更改内容的信息。
class Festival: Object {
@objc dynamic var festivalId: String = UUID().uuidString
@objc dynamic var name: String = ""
@objc dynamic var town: String = ""
@objc dynamic var initialDate: Date = Date()
@objc dynamic var finalDate: Date = Date()
let program = List<DailyProgram>()
override static func primaryKey() -> String? {
return "festivalId"
}
}
class DailyProgram: Object{
@objc dynamic var day: Date = Date()
let events = List<Event>()
}
class Event: Object {
@objc dynamic var name: String = ""
@objc dynamic var local: String = ""
@objc dynamic var time: Date = Date()
}
我很清楚 Realm 中对象通知的存在。我认为这些可能是我的问题的解决方案。我知道如何在单个对象上实现对象通知。但是,我不知道如何在嵌套对象的情况下实现这些类型的通知。
简答:
在事件与其所属的节日之间创建反向关系。然后根据属于特定节日的事件获得结果并观察它们。然后,当为该节日添加、修改或删除任何活动时,您将收到通知。
基于长代码的答案。从修改您的领域对象开始(我去掉了属性以缩短代码)
class Festival: Object {
@objc dynamic var festivalId: String = UUID().uuidString
@objc dynamic var name: String = ""
let program = List<DailyProgram>()
override static func primaryKey() -> String? {
return "festivalId"
}
}
class DailyProgram: Object {
@objc dynamic var day = ""
@objc dynamic var festival: Festival! //add this
let events = List<Event>()
}
class Event: Object {
@objc dynamic var daily_program: DailyProgram!
@objc dynamic var festival: Festival! //add this
@objc dynamic var name: String = ""
}
然后创建确保添加反向关系的对象。注意 var 命名,f0 = Fest 0,f1 = Fest 1,然后 dp = DailyProgram 和 e = Event。这样做是为了更容易看到层次结构。
let f0 = Festival()
f0.name = "Fest 0"
let f0dp0 = DailyProgram()
f0dp0.day = "Monday"
f0dp0.festival = f0
let f0dp0e0 = Event()
f0dp0e0.name = "Morning event"
f0dp0e0.daily_program = f0dp0
f0dp0e0.festival = f0
let f0dp0e1 = Event()
f0dp0e1.name = "Afternoon event"
f0dp0e1.daily_program = f0dp0
f0dp0e1.festival = f0
let f1 = Festival()
f1.name = "Fest 1"
let f1dp0 = DailyProgram()
f1dp0.day = "Monday"
f1dp0.festival = f1
let f1dp0e0 = Event()
f1dp0e0.name = "Evening event"
f1dp0e0.daily_program = f1dp0
f1dp0e0.festival = f1
let f1dp0e1 = Event()
f1dp0e1.name = "Midnight event"
f1dp0e1.daily_program = f1dp0
f1dp0e1.festival = f1
上面创建了两个节日,每个节日都有一个周一的每日节目,然后每个周一的节目都有两个活动。
然后我们加载我们的结果并添加一个观察者。在这种情况下,我们对 Fest 1 活动感兴趣。
var eventResults: Results<Event>? = nil
var eventNotificationToken: NotificationToken? = nil
func loadAndObserveFestivalEvents() {
if let realm = gGetRealm() {
self.eventResults = realm.objects(Event.self).filter("festival.name == %@", "Fest 1")
self.observeEvents()
}
}
func observeEvents() {
self.eventNotificationToken = self.eventResults!.observe { (changes: RealmCollectionChange) in
switch changes {
case .initial:
print("initial event load complete")
if let results = self.eventResults { //just shows events are loaded
for e in results {
let d = e.daily_program.day
let f = e.festival.name
print(f, d, e.name)
}
}
break
case .update(_, let deletions, let insertions, let modifications):
print(" handle event delete, insert or mod")
if let results = self.eventResults { //shows the list including the newly added event
for e in results {
let d = e.daily_program.day
let f = e.festival.name
print(f, d, e.name)
}
}
break
case .error(let error):
fatalError("\(error)")
break
}
}
}
此时我们已准备好向 Fest 1 的星期一活动添加一个活动,然后收到添加该活动的通知。
func addEvent() {
if let realm = gGetRealm() {
let dp = realm.objects(DailyProgram.self).filter("festival.name == %@ && day == %@", "Fest 1", "Monday")
if let daily = dp.first {
let eventToAdd = Event()
eventToAdd.daily_program = daily
eventToAdd.festival = daily.festival
eventToAdd.name = "Super Duper Event"
try! realm.write {
daily.events.append(eventToAdd)
}
}
}
}
代码的最后一部分创建一个结果对象,其中填充了 Fest 1,星期一的 DailyProgram。
然后我创建一个新事件,确保我 link 将其返回到 Fest 1 音乐节,然后将其添加到 DailyPrograms 事件列表中。
此代码可以大大缩短并利用 LinkingObject 自动创建 link 返回。然而,在这种情况下,一个事件将永远只属于一个 DailyProgram 和 Festival,所以它并不是真正需要的。
注意gGetRealm
是我用来连接realm的单例。