请检查以下Team
和Member
的模型类。在团队中,members
可以包含Member
列表。 JSON对象用于在服务方法中创建和更新团队。会员可以单独更新。在Member
对象中,有一个属性lastSeenAt
,根据该成员的活动进行更新。
class Team: Object {
dynamic var channelId: String? = nil
dynamic var title: String? = nil
let members = List<Member>()
override class func primaryKey() -> String? {
return "channelId"
}
}
class Member: Object {
dynamic var _id: String?
dynamic var lastSeenAt: Date?
override class func primaryKey() -> String? {
return "_id"
}
}
服务方法更新团队和成员
func createAndUpdateTeams(_ teams: [[String:Any]]?) {
DispatchQueue(label: "queueNameToCreate", attributes: []).async {
let realm = try! Realm()
try! realm.write({ () in
for team in teams! {
realm.create(Team.self, value: team, update: true)
}
})
}
}
func updateMember(_ member: [String:Any]?) {
DispatchQueue(label: "queueNameToUpdateMember", attributes: []).async {
let realm = try! Realm()
try! realm.write({
realm.create(MemberRealm.self, value: member, update: true)
})
}
}
要获得团队的实时更新,我在Results<Team>
添加了一个通知块,如下所示:
teams = realm.objects(Team.self);
notificationToken = teams?._addNotificationBlock({ [weak self](changes) in
switch( changes ) {
case .initial:
self?.tableView?.reloadData()
case .update(_,let deletions,let insertions,let modifications):
print("Modified: deletions: \(deletions.count),\n insertions: \(insertions.count),\n modifications:\(modifications.count)")
self?.tableView?.reloadData()
case .error:
break
}
})
问题
当我调用updateMember(_:)
来更新Member
对象时,会调用通知块。虽然团队中没有更新,但TableView会使用相同的数据加载自身。作为效果,屏幕会针对每个updateMember(_:)
来电波动。
Github Sample Project生成问题 https://github.com/milankamilya/RealmUpdateTest
答案 0 :(得分:1)
您看到的是Realm
的预期行为。即使只有一个对象在完成块范围内的一个对象的一对多关系中更新,也会通过设计调用通知块。由于您的Team
类与Member
具有一对多关系,因此在所有Team
个对象上设置通知块时,通知块将在每次调用时调用如果Member
对象存储在您的Team
个对象members
属性中,则会对其进行更新。
请参阅this GitHub问题更详细地解释了该问题。
您可以使用的一种解决方法是将members
定义为LinkingObjects
而不是List
。我自己没有尝试过,但根据链接的GitHub问题的答案,当一个对象发生变化时,通知块不会被调用LinkingObjects
,而使用的是一对多关系List
。
要将LinkingObjects
用作members
,您需要按以下方式更改模型类:
class Team: Object {
dynamic var channelId: String? = nil
dynamic var title: String? = nil
let members = LinkingObjects(fromType: Member.self, property: "team") //finds all Member objects, where Member.team = self (this team)
override class func primaryKey() -> String? {
return "channelId"
}
}
class Member: Object {
dynamic var _id: String?
dynamic var team:Team?
dynamic var lastSeenAt: Date?
override class func primaryKey() -> String? {
return "_id"
}
}