Swift 4:为每个CollectionView项具有不同的值

时间:2017-11-02 09:37:15

标签: swift firebase

练习,练习和练习..

今天提出了一个想法。制作一个简单的测验应用程序。我有一切计划好的,所以当谈到CollectionView部分时,事情变得如此复杂。

所以我有1个部分和4个项目。和一个快速的结构。 这是我的结构代码

struct Questions {
    let QuestionTitle : String
    let QuestionAnswer0 : String
    let QuestionAnswer1 : String
    let QuestionAnswer2 : String
    let QuestionAnswer3 : String
    let CorrectAnswer : String // leave this one
}

但是我有一个示例数据插入到这个结构中,从QuestionAnswer0到QuestionAnswer3有它的字符串

这是我的CollectionView代码

func numberOfSections(in collectionView: UICollectionView) -> Int {
   return 1 // one section
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
   return 4 // four answers
}

复杂的部分是,问题来自firebase。我的firebase结构看起来像这个Image

以及我加载它们的方式

func loadQuestions() {
    var ref: DatabaseReference!

    ref = Database.database().reference()

    //let userID = Auth.auth().currentUser?.uid

    ref.child("Questions").observe( .childAdded, with: { (snapshot) in

        let value = snapshot.value as? NSDictionary
        let questionTitle1 = snapshot.key

        let An0 = value?["0"] as? String ?? ""
        let An1 = value?["1"] as? String ?? ""
        let An2 = value?["2"] as? String ?? ""
        let An3 = value?["3"] as? String ?? ""
        let crct = value?["Correct"] as? String ?? ""

        self.QuestionsLoaded.insert(Questions(QuestionTitle : questionTitle1 ,QuestionAnswer0: An0 , QuestionAnswer1: An1 , QuestionAnswer2: An2 , QuestionAnswer3: An3, CorrectAnswer: crct) , at: 0)

        self.MyCollectionView.reloadData()

    }) { (error) in
        print(error.localizedDescription)
    }    
}

好的,所以现在加载数据,让我们把它们排序。我的CollectionView代码

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let  cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell0CollectionViewCell
    if indexPath.section == 0 {
        if indexPath.item == 0 {
            cell.qn.text = QuestionsLoaded[indexPath.row].QuestionAnswer0
        } else if indexPath.item == 1 {
            cell.qn.text = QuestionsLoaded[indexPath.row].QuestionAnswer1
        } else if indexPath.item == 2 {
            cell.qn.text = QuestionsLoaded[indexPath.row].QuestionAnswer2
        } else if indexPath.item == 3 {
            cell.qn.text = QuestionsLoaded[indexPath.row].QuestionAnswer3
        }
    }
    return cell
}

最后,在发布的第一时刻,它返回

  

致命错误:索引超出范围

非常感谢你帮助我

修改 我知道导致此错误的原因,在我的问题加载之前,集合视图会自动返回四个空项,这会导致索引超出范围

这里有日志

[]
[]
[]
[]

几分钟后,崩溃但问题加载

无论如何要延迟这几秒,或者一些正确的方法来解决这个问题?

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
   return 4 // four answers
}

1 个答案:

答案 0 :(得分:0)

那是因为QuestionsLoaded数组中只有 一个元素,因此您尝试访问QuestionsLoaded[indexPath.row],导致“索引超出范围”错误。问题是你在说:

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
   return 4 // four answers
}

并且您正在尝试根据项目的数量获取元素,以使其更清晰,在尝试绘制第二个单元格时 - 例如 - indexPath.row的值将为1,这是 not 与数组元素索引兼容(QuestionsLoaded只包含1个元素,即:QuestionsLoaded[0]是唯一有效的元素。)

要解决这个问题,您需要像这样实现它:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let  cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell0CollectionViewCell
    if indexPath.section == 0 {
        if indexPath.item == 0 {
            cell.qn.text = QuestionsLoaded[0].QuestionAnswer0
        } else if indexPath.item == 1 {
            cell.qn.text = QuestionsLoaded[0].QuestionAnswer1
        } else if indexPath.item == 2 {
            cell.qn.text = QuestionsLoaded[0].QuestionAnswer2
        } else if indexPath.item == 3 {
            cell.qn.text = QuestionsLoaded[0].QuestionAnswer3
        }
    }
    return cell
}

<强>更新

如果QuestionsLoaded为空,numberOfItemsInSection数据源方法应返回0:

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
   return QuestionsLoaded.isEmpty ? 0 : 4
}
除非cellForItemAt数组中有元素,否则

会导致永远不会到达QuestionsLoaded数据源方法。显然,在调用self.MyCollectionView.reloadData()之后,将使用非空数据源再次调用该方法,它应该按预期工作。