Swift中Firebase实时数据库更新好友数据并刷新TableView问题
我来帮你解决这个Firebase实时更新的问题!
核心问题诊断
你自己已经点出了关键:watchForChangesInMyFriends函数里找到好友索引后,只是把原对象重新赋值给数组,完全没用到Firebase返回的最新snapshot去生成新的FriendClass实例——数组里的元素还是旧数据,TableView刷新当然看不出变化。
修正后的关键代码
直接修改watchForChangesInMyFriends函数,用新snapshot创建更新后的好友对象,同时别忘了UI操作必须在主线程执行:
func watchForChangesInMyFriends() { let usersRef = self.ref.child("profiles") usersRef.observe(.childChanged, with: { snapshot in let key = snapshot.key if let friendIndex = self.myFriendsDataSource.firstIndex(where: { $0.uid == key} ) { // 用最新的snapshot生成更新后的FriendClass实例 let updatedFriend = FriendClass(withSnapshot: snapshot) print("found user \(updatedFriend.batteryStatus), updating") self.myFriendsDataSource[friendIndex] = updatedFriend // Firebase回调在后台线程,必须切回主线程刷新UI DispatchQueue.main.async { self.tableView.reloadData() } } }) }
额外优化:避免重复监听&主线程刷新
还有两个小细节能帮你避免潜在bug:
- 不要重复添加监听:你现在在
loadFriend里每加载一个好友就调用一次watchForChangesInMyFriends,这会导致Firebase重复注册监听事件。应该把监听的调用移到所有好友加载完成后,只执行一次:
func loadUsersFriends() { let uid = "zzV6DQSXUyUkPHgENDbZ9EjXVBj2" let myFriendsRef = self.ref.child("userFriends").child(uid) myFriendsRef.observeSingleEvent(of: .value, with: { snapshot in let uidArray = snapshot.children.allObjects as! [DataSnapshot] for friendsUid in uidArray { self.loadFriend(withUid: friendsUid.key) print(friendsUid) } // 所有好友加载完成后,再注册实时监听 self.watchForChangesInMyFriends() }) }
- 所有UI更新都要在主线程:
loadFriend里的tableView.reloadData()同样需要包裹在DispatchQueue.main.async里,因为Firebase的observeSingleEvent回调也是在后台线程执行的:
func loadFriend(withUid: String) { let thisUserRef = self.ref.child("profiles").child(withUid) thisUserRef.observeSingleEvent(of: .value, with: { snapshot in let aFriend = FriendClass(withSnapshot: snapshot) self.myFriendsDataSource.append(aFriend) print(self.myFriendsDataSource) DispatchQueue.main.async { self.tableView.reloadData() } // 这里不要再调用watchForChangesInMyFriends了! }) }
这样修改后,当Firebase数据库中的好友资料(比如位置、电量)更新时,你的数据源数组会立刻拿到最新的对象,TableView也能正确刷新显示最新内容啦。
内容的提问来源于stack exchange,提问作者Newbie
相关产品推荐
相关产品推荐

