这是一个问题。目前,我想在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
    }
    

  • 希望能给你一些线索。

    10-08 05:26