孩子改变了扇出

时间:2017-09-23 03:28:53

标签: ios swift firebase firebase-realtime-database

考虑以下数据库结构 -

tasks
    task1
        title: "My first task"
        uid: "user1"
user-tasks
    user1
        task1: true

要观察特定用户任务的变化,您可能会想要实现类似的东西 -

ref.child("user-tasks").child(uid).observe(.childChanged...

但问题是对标题的任何更改都不会反映在用户任务中,因此不会触发childChanged事件。如果您观察所有任务,那么对其他用户的任务的任何更改都将导致观察者不必要地执行。此外,所需的实现将处理其他用户/设备对任务的更新,并且更新将正确触发。

到目前为止,我唯一的想法是用更新后更新的时间戳替换true,并触发观察者。还有更好的方法吗?

3 个答案:

答案 0 :(得分:0)

这取决于你想要完成的事情。例如:如果要显示当前用户的任务名称列表,您确实需要两种类型的侦听器与您当前的数据模型:

  1. /user-tasks下用户的任务列表的监听器。
  2. /tasks下用户的每个可见任务的侦听器,以获取名称。
  3. 这会导致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任务。这取决于你可能需要哪些数据。