Firebase多个观察者复制单元格 [英] Firebase Multiple observer duplicates cell
问题描述
我想在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屋!