UICollectionView给出“索引超出范围”错误

时间:2018-10-28 12:08:43

标签: ios swift xcode uicollectionview

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

1 个答案:

答案 0 :(得分:1)

在这种方法中

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
  return 24
}

您告知集合视图将始终有24行,因此在加载视图时,它将开始在集合视图中获取24行的内容。

但是,您的memberData数组的定义如下:

var memberData = [MemberData]()

意味着最初它将是空的。

然后,您开始向memberData中的getMemberData添加内容,但是此时,您的收藏夹视图可能已经开始填充,并且正在请求第5行的内容...没有任何元素的数组中,就会崩溃。

所以您可以做的是:

  1. numberOfItemsInSection更改为返回静态值,而是返回memberData中的实际项数,如下所示:

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return memberData.count
    }
    

    一旦您完成了在memberData函数中将数据加载到getMemberData中的操作,就告诉要重新加载集合视图,它将再次贯穿构建集合视图的整个过程,这次是数据。

  2. cellForItemAt中,您可以确保不要尝试获取不存在的内容:

    if indexPath.row < memberData.count {
        let cellData = memberData[indexPath.row
        //and so on
    }
    

希望能为您提供一些线索。