这是一个问题。目前,我想在UITableView中显示UITableViewCell以获取在数据库中注册的用户数。但是,它在UITableViewDataSOurce方法(cellForItemAt)中变为“索引超出范围”。
我了解该错误的含义,但不知道为什么会发生这种错误。你可以告诉我吗?
import UIKit
import Firebase
import FirebaseStorage
import FirebaseFirestore
import SDWebImage
struct MemberData {
var image: URL?
var text: String?
}
class MemberSelectViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
let statusBsr = UIApplication.shared.statusBarFrame.height
let db = Firestore.firestore()
var teamIDFromFirebase: String = ""
var fireAuthUID = (Auth.auth().currentUser?.uid ?? "no data")
var memberData = [MemberData]()
var memberImageArr = [Any]()
var memberTextArr = [Any]()
var memberUserIDArr = [Any]()
override func viewDidLoad() {
super.viewDidLoad()
let collectionView = UICollectionView(frame: CGRect(x: 0, y: statusBsr, width: self.view.frame.width, height: self.view.frame.size.height - statusBsr), collectionViewLayout: UICollectionViewFlowLayout())
let nibName = UINib(nibName: "memberCollectionViewCell", bundle: nil)
collectionView.register(nibName, forCellWithReuseIdentifier: "memberCell")
collectionView.delegate = self
collectionView.dataSource = self
self.view.addSubview(collectionView)
getMemberData(collectionView: collectionView)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 24
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let size = self.view.frame.size.width / 4
return CGSize(width: size, height: size)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
let inset = (self.view.frame.width / 4) / 5
return UIEdgeInsets(top: inset, left: inset, bottom: inset, right: inset)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return (self.view.frame.width / 4) / 5
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "memberCell", for: indexPath) as! memberCollectionViewCell
let cellData = memberData[indexPath.row]
cell.memberImage.sd_setImage(with: cellData.image)
cell.memberTitle.text = cellData.text
return cell
}
}
private extension MemberSelectViewController {
private func getMemberData(collectionView: UICollectionView) {
self.db.collection("users").document(self.fireAuthUID).addSnapshotListener { (snapshot3, error) in
guard let document3 = snapshot3 else {
print("erorr2 \(String(describing: error))")
return
}
guard let data = document3.data() else { return }
self.teamIDFromFirebase = data["teamID"] as? String ?? ""
self.db.collection("users").whereField("teamID", isEqualTo: self.teamIDFromFirebase).getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
return
} else {
var i = 0
for document in querySnapshot!.documents {
guard var documentData: [String: Any] = document.data() else { return }
self.memberImageArr.append((documentData["image"] as? String)!)
self.memberTextArr.append((documentData["name"] as? String)!)
self.memberData.append(MemberData(image: URL(string: self.memberImageArr[i] as! String), text: self.memberTextArr[i] as! String))
i += 1
}
}
}
}
}
}
最佳答案
用这种方法
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 24
}
您通知集合视图将始终有24行,因此在加载视图时,它将开始在集合视图中获取24行的内容。
但是,您的
memberData
数组的定义如下:var memberData = [MemberData]()
意味着最初它是空的。
然后,您开始向
memberData
中的getMemberData
添加内容,但是到那时,您的集合视图可能已经开始填充,并且正在向第5行(例如)请求内容...在没有元素的数组中,这将崩溃。因此,您可以做的是:
numberOfItemsInSection
更改为不返回静态值,而是返回memberData
中的实际项目数,如下所示:func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return memberData.count
}
将数据加载到
memberData
函数中的getMemberData
中后,您就告诉要重新加载集合视图,并且它将再次遍历构建集合视图的整个过程,这次是使用数据。 cellForItemAt
中的if indexPath.row < memberData.count {
let cellData = memberData[indexPath.row
//and so on
}
希望能给你一些线索。