我已经被困了一段时间,任何建议将不胜感激。我正在创建一个使用Firebase数据库的应用程序,并且创建了5个类,这些类在Firebase中保存不同的数据。我正在创建一个需要显示5个类中的每个类的信息的表视图(配置文件名称,图像,然后是有关联赛的信息以及有关得分的信息)。因此,在新的类中,我创建了一个函数,该函数从每个类的firebase中调用数据。 例如:获取X联赛{ 对于联盟中的每个球员{ 获取玩家信息 然后获取分数 然后不停地 一旦我们拥有所有信息,追加到新数组 } 然后对数组进行排名 }
所有这些运行之后,我想在VC上重新加载表视图
因此,我的解决方案适用于原始负载,但是如果我退出并重新进入屏幕,则名称和图像会重复。
确切地说,当索引打印到控制台时,我得到了 “玩家1:扎克” “玩家2:约翰” 但是,屏幕上反复显示John的图像和姓名。但是,只有该类……所有其他数据都保留在应有的位置。原始函数都以相同的方式编写。
我认为这与内存管理有关,还是写得不好我的完成处理程序?
这是新数组类中的代码:
您还会注意到,我的complete()位于我讨厌的for循环中,但这是我可以在完成之前完成该功能的唯一方法。否则,该功能会在数据准备就绪之前完成。>
func getLeaderboard(leagueID: String, completion: @escaping ()->()) {
print("League Count After removeAll \(self.rankedGolfers.count)")
self.leagueMembers.getLeagueMembers(leagueID: leagueID) {
print("HANDLER: Step 1: Get League Members")
for member in self.leagueMembers.leagueMembers {
print("Golfer Member ID: \(member.userID)")
self.golferInfo.getGolferInfo(userKey: member.userID, completion: {
print("HANDLER: Step 2: Get player profile info")
print("Golfer Name3: \(self.golferInfo.golfers[0].firstName) \(self.golferInfo.golfers[0].lastName)")
self.handicapHelper.getRounds(userID: member.userID, completion: {
print("HANDLER: Step 3: Get players Handicap")
print("Golfer Handicap3: \(self.golferInfo.golfers[0].lastName): \(self.handicapHelper.handicap)")
self.leagueInfo.getLeagueInfo(leagueID: leagueID, completion: {
print("HANDLER: Step 4: Get league info")
let golferIndex = self.golferInfo.golfers[0]
let memberInfoIndex = self.leagueInfo.leagueInfo[0]
let golferID = member.userID
let profileImg = golferIndex.profileImage
let golferName = "\(golferIndex.firstName) \(golferIndex.lastName)"
let handicap = self.handicapHelper.handicap
let golferLeaguePardieScore = member.pardieScore
let leagueRoundsPlayed = member.numberOfRounds
let roundsRemaining = memberInfoIndex.leagueMinRounds - leagueRoundsPlayed
let currentWinnings = member.currentWinnings
let newGolfer = Leaderboard(golferID: golferID, profileImg: profileImg ?? "No Img", golferName: golferName, golferHandicap: handicap, golferLeaguePardieScore: golferLeaguePardieScore, roundsPlayedInLeague: leagueRoundsPlayed, roundsRemaining: roundsRemaining, currentWinnings: currentWinnings)
self.rankedGolfers.append(newGolfer)
print("HANDLER: Step 5: Add golfer to array")
//print("Golfer Name 4: \(newGolfer.golferName)")
//print("Rounds Remaining: \(newGolfer.roundsRemaining)")
print("league Member Count: \(self.rankedGolfers.count)")
self.getLeaderboardRanking()
print("HANDLER: Step 6: Rank Array")
//print("COMPLETION: \(self.rankedGolfers.count)")
completion()
})
})
})
}
}
}
谢谢您的帮助!
答案 0 :(得分:0)
我认为我们可以使用DispatchGroup解决此问题,这将确保为每个用户加载所有数据,然后将用户添加到用作tableView dataSource的数组中,然后在完成后重新加载tableView。
为简单起见,我们将从UserInfo类开始,该类存储其uid,名称,喜欢的食物和障碍。
class UserInfoClass {
var uid = ""
var name = ""
var favFood = ""
var handicap = 0
}
和用作tableView的数据源的类var数组
var userInfoArray = [UserInfoClass]()
然后,假设我们具有这样的结构...
users
uid_0
name: "Leroy"
handicaps
uid_0
amt: 4
fav_foods
uid_0
fav_food: "Pizza"
...这是一个读取所有用户的函数,然后遍历每个用户,并使用其名称和uid填充UserInfoClass,并创建一个调度组,该调度组也填充其最喜欢的食物和障碍。完成此操作后,会将用户添加到dataSource数组中,并且在读取所有用户后,将重新加载tableView以显示信息。
func loadUsersInfoAndHandicap() {
let ref = self.ref.child("users")
self.userInfoArray = []
ref.observeSingleEvent(of: .value, with: { snapshot in
let group = DispatchGroup()
let allUsers = snapshot.children.allObjects as! [DataSnapshot]
for user in allUsers {
let uid = user.key
let name = user.childSnapshot(forPath: "name").value as? String ?? "No Name"
let aUser = UserInfoClass()
aUser.uid = uid
aUser.name = name
group.enter()
self.loadFavFood(withUid: uid) {favFood in
aUser.favFood = favFood
group.leave()
}
group.enter()
self.loadHandicap(withUid: uid) { handicap in
aUser.handicap = handicap
group.leave()
}
group.notify(queue: .main) {
self.userInfoArray.append(aUser)
}
}
group.notify(queue: .main) {
print("done, reload the tableview")
for user in self.userInfoArray {
print(user.uid, user.name, user.favFood, user.handicap)
}
}
})
}
从主要用户节点读取用户名和uid,这是读取他们最喜欢的食物和障碍的两个函数。
func loadFavFood(withUid: String, completion: @escaping(String) -> Void) {
let thisUser = self.ref.child("userInfo").child(withUid)
thisUser.observeSingleEvent(of: .value, with: { snapshot in
let food = snapshot.childSnapshot(forPath: "fav_food").value as? String ?? "No Fav Food"
completion(food)
})
}
func loadHandicap(withUid: String, completion: @escaping(Int) -> Void) {
let thisUser = self.ref.child("handicaps").child(withUid)
thisUser.observeSingleEvent(of: .value, with: { snapshot in
let handicap = snapshot.childSnapshot(forPath: "amt").value as? Int ?? 0
completion(handicap)
})
}
请注意,self.ref指向我的firebase,因此请替换为您的 firebase的引用。
请注意,我输入的内容非常快,基本上没有错误检查,因此请相应添加。