考虑以下数据库结构 -
tasks
task1
title: "My first task"
uid: "user1"
user-tasks
user1
task1: true
要观察特定用户任务的变化,您可能会想要实现类似的东西 -
ref.child("user-tasks").child(uid).observe(.childChanged...
但问题是对标题的任何更改都不会反映在用户任务中,因此不会触发childChanged事件。如果您观察所有任务,那么对其他用户的任务的任何更改都将导致观察者不必要地执行。此外,所需的实现将处理其他用户/设备对任务的更新,并且更新将正确触发。
到目前为止,我唯一的想法是用更新后更新的时间戳替换true,并触发观察者。还有更好的方法吗?
答案 0 :(得分:0)
这取决于你想要完成的事情。例如:如果要显示当前用户的任务名称列表,您确实需要两种类型的侦听器与您当前的数据模型:
/user-tasks
下用户的任务列表的监听器。/tasks
下用户的每个可见任务的侦听器,以获取名称。这会导致1 + N个侦听器,其中N取决于UI中可见的任务数。虽然这通常不是Firebase的技术问题,但在代码中正确管理侦听器需要花费一些精力。
另一种方法是在/user-tasks
下复制每项任务的名称:
user-tasks
user1
task1: "My first task"
使用此数据结构,您只需要监听/user-tasks
以获取显示任务列表的所有信息。但反过来,你现在必须在写操作中处理keeping the duplicated data up to date。
这里没有单一的最佳实践:这完全取决于您的应用程序的需要以及您是否愿意复制数据,管理监听器以及应用程序的读写性能要求。
答案 1 :(得分:0)
在这种情况下,我的确建议你使用你的任务时间戳而不是真的。
然后每次更改对象中的某些内容(如标题或其他内容)时,您还需要更新此值(使用updateChildValues)
这将允许您知道是否(以及何时)发生了更新,并且它还会调用您的childChanged或childAdded观察者。
您的数据库看起来像这样,这与您展示的内容完全相同,但用更有意义的值替换为true,即时间戳:
root/
|___ tasks/
| |___ taskID1
| |___ title : task_title
| |___ timestamp : task_timestamp1
| ...
|
|___ user_tasks/
| |___ userID1
| |___ taskID1: task_timestamp1
| |___ taskID2: task_timestamp2
| ...
| ...
可能还有其他一些解决方案,但这是我现在能想到的最简单的解决方案,这样做不需要在项目中进行很多更改。
答案 2 :(得分:0)
使用查询。
let taskQuery = taskRef.queryOrdered(byChild: "uid").queryEqual(toValue: "user1")
taskQuery.observe(.childAdded, with: { snapshot in
print(snapshot)
})
只有在将任务添加到user1的tasks节点时才会触发此操作。为.childChanged和.childRemoved添加类似的代码。
此外,在用户节点中存储task1:true可能是多余的,因为您始终可以在任务节点中查询user1任务。这取决于你可能需要哪些数据。