2017-08-03 67 views
1

我想在tableView中顯示當前用戶的朋友,但我無法讓它完美工作,當列表中的某個人更改他的名字時,單元格會重複。Firebase多個觀察者複製單元格

JSON:

{ 
    "users" : { 
    "friends_requests" : { 
     "EeLIxkOEfhMUlsM8WGnHdgeT8xW2" : { 
     "friends" : { 
      "WWOdh96Yr3Qs4N3GWDVq3OlQFfB2" : true 
     } 
     }, 
     "WWOdh96Yr3Qs4N3GWDVq3OlQFfB2" : { 
     "friends" : { 
      "EeLIxkOEfhMUlsM8WGnHdgeT8xW2" : true 
     } 
     } 
    }, 
    "profile" : { 
     "EeLIxkOEfhMUlsM8WGnHdgeT8xW2" : { 
     "birthday" : "02/08/2017", 
     "displayname" : "user2", 
     "email" : "[email protected]", 
     "gender" : "M" 

     }, 
     "WWOdh96Yr3Qs4N3GWDVq3OlQFfB2" : { 
     "birthday" : "02/08/2017", 
     "displayname" : "user1", 
     "email" : "[email protected]", 
     "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文件。

+0

查看'self.friendList.removeAll()'嘗試打印'friendList.count'後查看是否所有用戶都被刪除。此外,你應該包括用戶代碼類與您的代碼 – Stefan

+0

@斯特凡謝謝,我已經測試,並清空列表。我編輯了我的問題。 – Sam

回答

0

嘗試改變

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,如果有,它會更新匹配的userID用戶的顯示名稱。如果friendsList中沒有用戶與userID匹配,則會將該用戶附加到friendsList的末尾,因爲它是尚未在陣列中的新用戶。

+0

謝謝,我已經這樣做了,但名稱不會更新,直到當前用戶再次打開viewcontroller,我希望每次更改他們的名稱時更新用戶名,就像我想直接在tableView中看到更改。 – Sam

+0

好吧我會更新我的答案,以允許該功能,但首先我需要知道多個用戶是否有可能具有相同的顯示名稱?對每個用戶來說它是獨一無二的,還是可以有多個用戶擁有相同的顯示名稱? – RPatel99

+0

如果不是,您可能想要將'userID'添加爲'Userr'的屬性並將其設置爲等於用戶的pushID(即「EeLIxkOEfhMUlsM8WGnHdgeT8xW2」),因爲即使在將來的情況下,有一個屬性可以唯一地區分一個'用戶'與另一個。 – RPatel99