将一组对填充到 Firebase 的 tableView 中以仅显示前 3 个最高分 [英] Populating an array of pairs into a tableView from Firebase to display only the top 3 highest scores
问题描述
我试图用一对数组(一个 Int,一个 String)填充我的 tableView.不幸的是,我在理解为什么它不起作用时遇到了一些麻烦,因为我似乎无法填充 tableView,我收到 indexOutOfRange 作为错误.我使用 firebase 作为我的数据库来检索我想要填充的数据.请看下面....
I am trying to populate my tableView with an array of pairs (one Int, one String). Unfortunately I am having some trouble understanding why it is not working as I can't seem to make the tableView populate, I receive indexOutOfRange as an error. I am using firebase as my database to retrieve the data I would like to populate. Please see below....
class Leaderboard: UIViewController, UITableViewDataSource, UITableViewDelegate {
private let padding = 12
private var quiz: Quiz!
private let backgroundImageView = UIImageView()
private let contentView = UIView()
private let leaderboardLabel = UILabel()
private let rankLabel = UILabel()
private let userLabel = UILabel()
private let scoreLabel = UILabel()
private let tableViewCellHeight: CGFloat = 60
private let bottomButton = BottomBorderedButtons()
var scoresArray = [ScoreClass]()
var topScoresTableView: UITableView = {
let tableView = UITableView()
return tableView
}()
override func viewDidLoad() {
super.viewDidLoad()
retrieveUserData()
setupViews()
}
required init(quiz: Quiz) {
super.init(nibName: nil, bundle: nil)
defer {
self.quiz = quiz
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
class ScoreClass {
var name = ""
var score = 0
init(withName: String, andScore: Int) {
name = withName
score = andScore
}
}
let ref = Database.database().reference()
func retrieveUserData() {
let postsRef = self.ref.child("Users")
let query = postsRef.queryOrdered(byChild: "highscore").queryLimited(toLast: 3)
query.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let snap = child as! DataSnapshot
let dict = snap.value as! [String: Any]
let name = dict["username"] as! String
let score = dict["highScore"] as! Int
let aScore = ScoreClass(withName: name, andScore: score)
self.scoresArray.insert(aScore, at: 0)
}
for s in self.scoresArray {
print(s.score, s.name)
}
})
self.topScoresTableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var countarr = 0
for s in self.scoresArray {
countarr = s.name.count
print(s.score, s.name)
print(countarr)
}
return countarr
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = topScoresTableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
let scoreClassObject = scoresArray[indexPath.row]
let name = scoreClassObject.name
let score = scoreClassObject.score
cell.backgroundColor = UIColor.clear
cell.usernameLabel.text = name
cell.resultLabel.text = String(score)
cell.rankNumberLabel.text = "\(indexPath.row + 1)"
print(scoresArray)
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 44
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 10.0
}
func setupViews() {
view.addSubview(backgroundImageView)
backgroundImageView.addSubview(contentView)
contentView.addSubview(leaderboardLabel)
contentView.addSubview(rankLabel)
contentView.addSubview(userLabel)
contentView.addSubview(scoreLabel)
contentView.addSubview(topScoresTableView)
contentView.addSubview(bottomButton)
self.backgroundImageView.snp.makeConstraints { (make) in
make.top.equalTo(topLayoutGuide.snp.bottom)
make.leading.equalToSuperview()
make.trailing.equalToSuperview()
make.bottom.equalToSuperview()
}
self.backgroundImageView.contentMode = UIViewContentMode.scaleAspectFill
self.backgroundImageView.isUserInteractionEnabled = true
self.backgroundImageView.image = UIImage(named: "Stars.png")
self.contentView.snp.makeConstraints { (make) in
make.edges.equalToSuperview()
}
contentView.backgroundColor = transluscentGrey
self.leaderboardLabel.snp.makeConstraints { (make) in
make.top.equalToSuperview()
make.leading.equalToSuperview()
make.trailing.equalToSuperview()
make.bottom.equalTo(topScoresTableView.snp.top).offset(-50)
make.centerX.equalToSuperview()
}
leaderboardLabel.textAlignment = .center
leaderboardLabel.numberOfLines = 0
leaderboardLabel.textColor = .white
leaderboardLabel.font = UIFont.boldSystemFont(ofSize: 28.0)
leaderboardLabel.text = "Leaderboard"
leaderboardLabel.backgroundColor = tableViewCell
self.rankLabel.snp.makeConstraints { (make) in
make.top.equalTo(leaderboardLabel.snp.bottom).offset(10)
make.leading.equalToSuperview().offset(padding)
make.height.equalTo(30)
}
rankLabel.textAlignment = .center
rankLabel.numberOfLines = 0
rankLabel.baselineAdjustment = .alignCenters
rankLabel.textColor = .white
rankLabel.font = UIFont(name: "SFUIDisplay-Medium", size: 3)
rankLabel.layer.cornerRadius = 5.0
rankLabel.clipsToBounds = true
rankLabel.text = "Rank"
self.userLabel.snp.makeConstraints { (make) in
make.top.equalTo(leaderboardLabel.snp.bottom).offset(10)
make.leading.equalTo(rankLabel.snp.trailing).offset(padding)
make.height.equalTo(30)
make.width.equalToSuperview().multipliedBy(0.50)
}
userLabel.textAlignment = .center
userLabel.numberOfLines = 0
userLabel.baselineAdjustment = .alignCenters
userLabel.textColor = .white
userLabel.font = UIFont(name: "SFUIDisplay-Medium", size: 3)
userLabel.layer.cornerRadius = 5.0
userLabel.clipsToBounds = true
userLabel.text = "Username"
self.scoreLabel.snp.makeConstraints { (make) in
make.top.equalTo(leaderboardLabel.snp.bottom).offset(10)
make.leading.equalTo(userLabel.snp.trailing).offset(padding)
make.height.equalTo(30)
make.trailing.equalToSuperview().offset(-padding)
}
scoreLabel.textAlignment = .center
scoreLabel.numberOfLines = 0
scoreLabel.baselineAdjustment = .alignCenters
scoreLabel.textColor = .white
scoreLabel.font = UIFont(name: "SFUIDisplay-Medium", size: 3)
scoreLabel.layer.cornerRadius = 5.0
scoreLabel.clipsToBounds = true
scoreLabel.text = "Score"
self.topScoresTableView.snp.makeConstraints { (make) in
make.leading.equalToSuperview()
make.trailing.equalToSuperview()
make.height.equalToSuperview().multipliedBy(0.65)
make.bottom.equalToSuperview().offset(-30)
}
topScoresTableView.delegate = self
topScoresTableView.register(TableViewCell.self, forCellReuseIdentifier: "cell")
topScoresTableView.dataSource = self
topScoresTableView.backgroundColor = UIColor.clear
self.bottomButton.snp.makeConstraints { (make) in
make.top.lessThanOrEqualTo(topScoresTableView.snp.bottom).offset(5)
make.width.equalTo(60)
make.bottom.equalToSuperview().offset(-5)
make.centerX.equalToSuperview()
}
self.bottomButton.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside)
self.bottomButton.backgroundColor = .yellow
}
}
推荐答案
让我们把它分解成几个部分
Let's decompose this into it's parts
从 Firebase 填充并保存名称和分数的 ScoreClass 对象
The ScoreClass objects which are populated from Firebase and hold the name and score
class ScoreClass {
var name = ""
var score = 0
init(withName: String, andScore: Int) {
name = withName
score = andScore
}
}
保存用作 tableView 数据源的 ScoreClass 对象的数组
The array to hold the ScoreClass objects that is used as the dataSource for tableView
var scoresArray = [ScoreClass]()
读取 Firebase 并填充数组的代码
The code to read Firebase and fill the array
func getScoresAndNamesFromFirebaseAndStuffIntoArray() {
let postsRef = self.ref.child("Users")
let query = postsRef.queryOrdered(byChild: "highscore").queryLimited(toLast: 3)
query.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let snap = child as! DataSnapshot
let dict = snap.value as! [String: Any]
let name = dict["username"] as! String
let score = dict["highScore"] as! Int
let aScore = ScoreClass(withName: name, andScore: score)
self.scoresArray.insert(aScore, at: 0)
}
self.topScoresTableView.reloadData()
})
}
然后是 tableView 委托方法.有三个函数来处理 tableView.这假设您在 tableView 中的文本单元格的标识符为 NameScoreCell
and then the tableView delegate methods. There are three functions to handle the tableView. This assumes your text cell in the tableView has an identifier of NameScoreCell
let textCellIdentifier = "NameScoreCell"
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return scoresArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: textCellIdentifier, for: indexPath as IndexPath)
let row = indexPath.row
let scoreObject = scoresArray[row]
let score = scoreObject.score
let name = scoreObject.name
cell.nameLabel?.text = name
cell.scoreLabel?.text = score
return cell
}
这篇关于将一组对填充到 Firebase 的 tableView 中以仅显示前 3 个最高分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!