练习,练习和练习..
今天提出了一个想法。制作一个简单的测验应用程序。我有一切计划好的,所以当谈到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
}
答案 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()
之后,将使用非空数据源再次调用该方法,它应该按预期工作。