使用数组中的新信息更新该对象并显示 tableview Swift
Posted
技术标签:
【中文标题】使用数组中的新信息更新该对象并显示 tableview Swift【英文标题】:Update that object with the new info in array and to display tableview Swift 【发布时间】:2019-10-30 10:51:25 【问题描述】:我正在使用 firebase 实时数据库并使用 usersFriend 和位置实现用户配置文件数据。我需要在对象数组中实现更新并在表格视图中显示更新的值。我已经尝试过,但我没有成功更新对象,然后重新加载 tableview。功能已开发。
我需要显示用新值交换的更新对象数组并显示在表格视图中。
var myFriendsDataSource = [FriendClass]()
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 )
let friend = self.myFriendsDataSource[friendIndex]
print("found user \(friend.batteryStatus), updating")
self.myFriendsDataSource[friendIndex] = friend
self.tableView.reloadData()
)
类:
class FriendClass
var uid = ""
var name = ""
var batteryStatus = Int()
var latitude = Double()
var longitude = Double()
var timeStamp = Int64()
//var profilePic
init(withSnapshot: DataSnapshot)
self.uid = withSnapshot.key
self.name = withSnapshot.childSnapshot(forPath: "name").value as? String ?? "No Name"
self.batteryStatus = withSnapshot.childSnapshot(forPath: "batteryStatus").value as? Int ?? 0
self.latitude = withSnapshot.childSnapshot(forPath: "latitude").value as? Double ?? 0.0
self.longitude = withSnapshot.childSnapshot(forPath: "longitude").value as? Double ?? 0.0
self.timeStamp = withSnapshot.childSnapshot(forPath: "timeStamp").value as? Int64 ?? 0
更新:
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)
)
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)
self.tableView.reloadData()
self.watchForChangesInMyFriends()
)
更新 2:
extension ViewController: UITableViewDelegate
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
return 70
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat
return 10
extension ViewController: UITableViewDataSource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return myFriendsDataSource.count
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "FriendListTableViewCell", for: indexPath) as! FriendListTableViewCell
let dic = myFriendsDataSource[indexPath.row]
cell.frndName.text = dic.name
return cell
【问题讨论】:
如果没有看到您的 tableView 代码,就无法告知为什么 tableView 没有正确重新加载。但是,您的watchFor...
函数中似乎存在逻辑错误:您得到 friendIndex
,在该索引处设置 friend
= 值,然后在不更改朋友的情况下,将该索引处的值设置回 friend
。基本上你设置的东西等于它自己。您的意思是在将 friend
放回数组之前更新它吗?
@flanker 我更新了我的问题并添加了两个主要功能,即loadFriend
和loadUsersFriends
。关于friend
包含模型中需要更改的匹配值。我需要从快照中读取信息,使用数组中的新信息更新该对象,然后重新加载 tableView。 watchFor...
已有新快照。
如果我没看错的话,watchFor...
方法会注册一个闭包,只要底层的 firebase 数据发生变化就会被调用,当闭包被调用时,它会提供该变化的快照,并且那么你想用新数据更新你的myFriendsDataSource
数组吗?正确的?目前您正在查找friend
的数组元素,将其打印出来,但实际上并未使用快照中的新数据对其进行更新?因此,假设tableView
数据源是myFriendsDataSource
数组,则tableView
中不会有任何更新
@flanker 是的,你的分析是正确的。
@flanker 是正确的。你正在做这个let friend = self.myFriendsDataSource[friendIndex]
,然后从数组中取出那个朋友,然后用这个self.myFriendsDataSource[friendIndex] = friend
把它放回去,而你想做的是self.myFriendsDataSource[friendIndex] = data from snapshot
【参考方案1】:
鉴于上述评论讨论,我认为您需要如下更新您的watchForChangesInMyFriends
方法,以便使用新朋友数据实际更新数据源。您还应该在主线程上进行所有 UI 更新,并且由于无法保证此闭包将在主线程上运行,因此您需要将 tableView 更新强制到主线程上。
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 )
let friend = self.myFriendsDataSource[friendIndex]
print("found user \(friend.batteryStatus), updating")
self.myFriendsDataSource[friendIndex] = FriendClass(withSnaphot: snapshot)
DispatchQueue.main.async
self.tableView.reloadData()
)
最好只更新已更改的 tableView 数据,而不是重新加载整个 tableView。您可能可以使用数组索引为适当的行生成IndexPath
,然后重新加载该行。如果没有看到您的 tableView 方法,我无法准确,但它可能看起来像这样:
let indexPath = IndexPath(row: friendIndex, section: 0)
DispatchQueue.main.async
self.tableView.reloadRows(at: [indexPath], with: .automatic)
【讨论】:
感谢您与self.tableView.reloadData()
完美配合。但是对于tableView.reloadRows
它不起作用。我已经用我的 tableview 方法更新了问题。
在 reloadRows 之前也需要self.
。如果失败,分享错误信息
我在 Xcode 中出现红色警告之前使用了self.
。但现在我再次尝试了它的工作。两种方式都成功。完美,非常感谢。 :)
@Newbie 这在 Firebase 闭包中不需要 DispatchQueue.main.async
。 Firebase 闭包中的所有 UI 调用都在主线程上完成。请参阅来自 Firebaser 的 this answer 了解更多信息。
谢谢@Jay。我从未使用过 Firebase,只是将其视为标准闭包,但很高兴向那些拥有的人让步:)以上是关于使用数组中的新信息更新该对象并显示 tableview Swift的主要内容,如果未能解决你的问题,请参考以下文章
JS 遍历对象数组并将值更改为匹配的键并创建一个包含对象数组 [0] 中的键的新对象