Firebase多个观察者复制单元格 [英] Firebase Multiple observer duplicates cell

查看:174
本文介绍了Firebase多个观察者复制单元格的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我想在tableView中显示当前的用户朋友,但是我无法完成它的工作。当列表中的某个人改变他的名字时, JSON:

$ p $ {
users:{
friends_requests:{

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


WWOdh96Yr3Qs4N3GWDVq3OlQFfB2:{
birthday:02/08/2017,
displayname:user1,
email :112@2.1,
性别:M









$代码如下:
$ b $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $' - > Void){
CURRENT_USER_FRIENDS_REF.observe(.value,其中:{(snapshot)in
self.friendList.removeAll()


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


$ b self.ref.child(users)。child(profile) .child(rest.key).observe(.value,其中:{(snapshot)in

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





让user = Userr()

user.displayname = dictionary [displayname] as?字符串

self.friendList.append(用户)


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


$ b $,withCancel:nil)



<我已经尝试了很多方法,并问这个问题许多次,但仍然不能得到它的工作,没有答案。

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



编辑:我使用的新观察者:
$ b $ $ p $ func showUsersObserver(_ update:@转义() - > Void){
CURRENT_USER_FRIENDS_REF.observe(.value,其中:{(snapshot)in
self.friendList.removeAll()


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



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

print(self.friendList.count)//每当用户更改他的名字或任何更改时,都会增加

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

update()
})

}


$ b //如果没有孩子,在这里运行完成而不是
如果snapshot.childrenCount == 0 {
update()





$ b $这样就可以得到他们的个人资料:

  func getUser(_ userID:String,completion:@转义(用户) - > Void){
USER_REF.child(userID).observe(.value,其中:{(snapshot)in

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



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



$ b完成(User(userEmail:email !, userID :id !, userDisplayName:DisplayName!))


$ b})
}

和friendList:

  class User {

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

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

self.email = userEmail
self.uid = userID
self.displayname = userDisplayName
$ b}
}

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

解决方案

尝试更改



<$ p $在
中有$ {code> self.ref.child(users)。child(profile)。child(rest.key).observe(.value, ..
})



($),$ {pre $ self.ref.child(users)。 in
...
})

观察会导致每次更改参考路径中的数据时, ... 中的代码都会运行。因此,每当参考路径中的数据发生更改时,都会附加到 friendList .observeSingleEvent 确保代码只执行一次。



如果您希望每当用户数据更改,继续使用 .observe ,然后在关闭中执行此操作:



uid为用户的按键

  guard let dictionary = snapshot.value as? [String:Any] else {
return
}
let userID = snapshot.key
如果让friend = self.friendsList.first(其中:{$ 0.uid == userID }){
friend.displayname = dictionary [displayname] as? String
friend.email = dictionary [email] as?字符串
friend.uid =字典[uid]为? String
//更新User类的任何其他属性
完成(friend)
}
else {
let id = dictionary [uid] as?字符串
让电子邮件=字典[电子邮件]为?字符串
让displayName = dictionary [displayname] as? String
//更新User类的其他属性

let user = User(userEmail:email,userID:id,userDisplayName:displayName)
self.friendsList.append(user )
完成(用户)
}

任何时候用户的配置文件改变,它都会检查 friendsList 数组中的任何用户是否具有相同的用户ID,如果是,则更新匹配的userID用户的显示名称。如果 friendsList 中没有用户匹配userID,则会将用户附加到 friendsList 的末尾,因为它是新的用户不在阵列中。


I want to show current user friends in tableView but I couldn't get it to work perfect, The cell duplicate when someone in the list change his name.

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"
      }
    }

  }
}

Here's the code:

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)

I've tried many ways and asked this question many times but still couldn't get it to work and no answers.

Please could someone help me to fix this.

Edit: New observer i use:

 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()
        }
    })
}

And this to get their profile data:

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!))



    })
}

And friendList:

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

    }
}

I was using Userr for testing. but User is main swift file.

解决方案

Try changing

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

to

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

.observe causes the code in the ... to run every time data at your reference path is changed. As a result, you append to friendList every time data at the reference path is changed. .observeSingleEvent ensures that code is only executed once.

If you want the cells to be updated whenever a user's data changes, keep using .observe and do this inside the closure:

Make User have a property called uid for the user's push key

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)
}

That code will make it so that any time a user's profile changes, it will check if any of the users in the friendsList array have the same userID, and if it does, it updates the matching userID user's displayname. If no user in the friendsList matches the userID, it will append the user to the end of friendsList because it is a new user that isn't in the array yet.

这篇关于Firebase多个观察者复制单元格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆