【问题标题】:Firebase Multiple observer duplicates cellFirebase 多个观察者重复单元格
【发布时间】:2017-08-03 15:28:09
【问题描述】:

我想在 tableView 中显示当前用户的朋友,但我无法让它完美地工作,当列表中的某人更改他的名字时,单元格重复。

JSON:

    {
  "users" : {
    "friends_requests" : {
      "EeLIxkOEfhMUlsM8WGnHdgeT8xW2" : {
        "friends" : {
          "WWOdh96Yr3Qs4N3GWDVq3OlQFfB2" : true
        }
      },
      "WWOdh96Yr3Qs4N3GWDVq3OlQFfB2" : {
        "friends" : {
          "EeLIxkOEfhMUlsM8WGnHdgeT8xW2" : true
        }
      }
    },
    "profile" : {
      "EeLIxkOEfhMUlsM8WGnHdgeT8xW2" : {
        "birthday" : "02/08/2017",
        "displayname" : "user2",
        "email" : "11@1.1",
        "gender" : "M"

      },
      "WWOdh96Yr3Qs4N3GWDVq3OlQFfB2" : {
        "birthday" : "02/08/2017",
        "displayname" : "user1",
        "email" : "112@2.1",
        "gender" : "M"
      }
    }

  }
}

代码如下:

var friendList = [Userr]()
func addFriendObserver(_ update: @escaping () -> Void) {
    CURRENT_USER_FRIENDS_REF.observe(.value, with: { (snapshot) in
        self.friendList.removeAll()


        let enumerator = snapshot.children
        while let rest = enumerator.nextObject() as? FIRDataSnapshot {



            self.ref.child("users").child("profile").child(rest.key).observe(.value, with: { (snapshot) in

                guard let dictionary = snapshot.value as? [String: Any] else {
                    return
                }




                let user = Userr()

                user.displayname = dictionary["displayname"] as? String

                 self.friendList.append(user)


                DispatchQueue.main.async {
                    self.tableview.reloadData()
                }



            }, withCancel: nil)

我尝试了很多方法并多次问过这个问题,但仍然无法让它发挥作用,也没有答案。

请有人帮我解决这个问题。

编辑:我使用的新观察者:

 func showUsersObserver(_ update: @escaping () -> Void) {
CURRENT_USER_FRIENDS_REF.observe(.value, with: { (snapshot) in
    self.friendList.removeAll()


    let keys = snapshot.children
    while let rest = keys.nextObject() as? FIRDataSnapshot {



        self.getUser(rest.key, completion: { (user) in
            self.friendList.append(user)

            print(self.friendList.count) // This increase each time when user changing his name! or any changes hits his profile.

            DispatchQueue.main.async {
                self.tableview.reloadData()
            }

            update()
        })

    }



    // If there are no children, run completion here instead
    if snapshot.childrenCount == 0 {
        update()
        }
    })
}

这是获取他们的个人资料数据:

func getUser(_ userID: String, completion: @escaping (User) -> Void) {
    USER_REF.child(userID).observe(.value, with: { (snapshot) in

        guard let dictionary = snapshot.value as? [String: Any] else {
            return
        }



        let id = dictionary["uid"] as? String
        let email = dictionary["email"] as? String
        let DisplayName = dictionary["displayname"] as? String




        completion(User(userEmail: email!, userID: id!, userDisplayName: DisplayName!))



    })
}

还有朋友列表:

class User {

var uid: String!
var displayname: String!
var email: String!


init(userEmail: String, userID: String, userDisplayName: String) {

    self.email = userEmail
    self.uid = userID
    self.displayname = userDisplayName

    }
}

我正在使用 Userr 进行测试。但用户是主要的 swift 文件。

【问题讨论】:

  • 查看self.friendList.removeAll() 尝试打印friendList.count 以查看是否所有用户都被删除。您还应该在代码中包含 Userr 类
  • @Stefan 谢谢,我已经测试过了,它清空了列表。我已经编辑了我的问题。

标签: ios swift uitableview firebase


【解决方案1】:

尝试改变

self.ref.child("users").child("profile").child(rest.key).observe(.value, with: { (snapshot) in
...
})

self.ref.child("users").child("profile").child(rest.key).observeSingleEvent(of: .value, with: { (snapshot) in
...
})

.observe 会导致 ... 中的代码在每次更改引用路径中的数据时运行。因此,每次更改引用路径中的数据时,您都会追加到 friendList.observeSingleEvent 确保代码只执行一次。

如果您希望在用户数据更改时更新单元格,请继续使用 .observe 并在闭包内执行此操作:

为用户的按键设置一个名为 uid 的属性

guard let dictionary = snapshot.value as? [String: Any] else {
    return
}
let userID = snapshot.key
if let friend = self.friendsList.first(where: {$0.uid == userID}) {
    friend.displayname = dictionary["displayname"] as? String
    friend.email = dictionary["email"] as? String
    friend.uid = dictionary["uid"] as? String
    //update any other properties of the User class
    completion(friend)
}
else {
    let id = dictionary["uid"] as? String
    let email = dictionary["email"] as? String
    let displayName = dictionary["displayname"] as? String
    //update other properties of the User class

    let user = User(userEmail:email, userID:id, userDisplayName:displayName)
    self.friendsList.append(user)
    completion(user)
}

该代码将在任何时候用户的个人资料发生更改时检查friendsList 数组中的任何用户是否具有相同的用户ID,如果是,它会更新匹配的用户ID 用户的显示名称。如果friendsList 中没有用户与用户ID 匹配,它将将该用户附加到friendsList 的末尾,因为它是一个尚未在数组中的新用户。

【讨论】:

  • 谢谢,我已经这样做了,但是在当前用户再次打开视图控制器之前,名称不会更新,我希望用户的名称在每次更改名称时更新,就像我想直接在 tableView 中看到更改一样。
  • 好的,我将更新我的答案以允许该功能,但首先我需要知道多个用户是否可以使用相同的显示名称?它是每个用户唯一的还是多个用户可以拥有相同的显示名称?
  • 如果没有,您可能希望将userID 添加为Userr 的属性并将其设置为等于用户的pushID(即“EeLIxkOEfhMUlsM8WGnHdgeT8xW2”),因为即使在未来的场景中,它也会拥有一个可以唯一区分 Userr 与另一个的属性会很有用。
  • @Sam 检查已编辑的帖子。将属性添加到 Userr 类,该类的类型为 String?,名为 userID
  • 没问题。很高兴我能帮上忙!
猜你喜欢
  • 2017-01-13
  • 2017-03-03
  • 2021-04-13
  • 2019-05-23
  • 2018-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多