尝试删除多个(以编程方式添加的)单元格后 CollectionView 崩溃
CollectionView crashing after I try deleting multiple (programmatically added) cells
我有一个带有非常简单数据源的 UICollectionView。它只是一个以编程方式更新的字符串数组。使用此 UICollectionView,我可以点击 select 多个单元格 - 然后可以使用删除按钮删除所有 selected 单元格。很简单,除了我有时会遇到致命错误:索引超出范围。
通过在另一个名为 "All Hobbies" 的集合视图中点击单元格以编程方式添加单元格 - 在 "All Hobbies" CV 中点击和 select 的任何单元格都会添加到 "My Hobbies." 我通过将点击的单元格的值附加到控制 My Hobbies CV 的数组来做到这一点。
问题
- 根据我 select 在我的爱好中的哪些单元格,删除按钮(下面的代码)有时会删除它们,或者有时会崩溃并出现致命错误:索引超出范围。它似乎不会在第一次删除时崩溃(如果有帮助的话。)
- 如果我的爱好中的单元格确实删除了,当我点击 "All Hobbies" 中的更多单元格时 - 它们添加到 "My Hobbies" 为 UIColor.red(表示它们是 selected。)(然后在我按下 delete btn 后会迟到崩溃。)单元格应添加为黄色。
我的数据似乎在删除后没有更新,当我再次尝试删除时,索引超出了范围。但是我在我的代码中找不到导致这种情况发生的问题(如果这确实是问题...)
Class 等级
let allHobbiesArray = ["Skiing", "Jogging", "Bicycling", "Basketball", "Cricket", "Being a Couch Potato", "Skiing", "Jogging", "Bicycling", "Basketball", "Cricket", "Being a Couch Potato", "Skiing", "Jogging", "Bicycling", "Basketball", "Cricket", "Being a Couch Potato", "Skiing", "Jogging", "Bicycling", "Basketball", "Cricket", "Being a Couch Potato"]
var myHobbiesArray = [String]()
var allSelected = [IndexPath]()
数据源
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView == allHobbiesCV {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ALL", for: indexPath) as! AllHobbiesCell
cell.allHobbiesLabel.text = allHobbiesArray[indexPath.row]
return cell
}
else {
let cell = myHobbiesCV.dequeueReusableCell(withReuseIdentifier: "MY", for: indexPath) as! MyHobbiesCell
cell.myHobbiesLabel.text = myHobbiesArray[indexPath.row]
return cell
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionView == allHobbiesCV {
return allHobbiesArray.count
}
else {
return myHobbiesArray.count
}
}
代表
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if collectionView == allHobbiesCV {
let cell = allHobbiesCV.cellForItem(at: indexPath) as! AllHobbiesCell
myHobbiesArray.append(allHobbiesArray[indexPath.row])
myHobbiesCV.reloadData()
for i in 0..<allSelected.count {
self.myHobbiesCV.selectItem(at: allSelected[i], animated: false, scrollPosition: [])
}
}
else {
let cell = myHobbiesCV.cellForItem(at: indexPath) as! MyHobbiesCell
cell.backgroundColor = UIColor.red // Red background to show that it's selected
// Store all of the selected cells in allSelected
allSelected = self.myHobbiesCV.indexPathsForSelectedItems!
}
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
if collectionView == allHobbiesCV {
let cell = allHobbiesCV.cellForItem(at: indexPath) as! AllHobbiesCell
cell.backgroundColor = UIColor.yellow
}
else {
let cell = myHobbiesCV.cellForItem(at: indexPath) as! MyHobbiesCell
cell.backgroundColor = UIColor.yellow
// update allSelected after deselect
allSelected = self.myHobbiesCV.indexPathsForSelectedItems!
}
}
正在删除单元格
@IBAction func deleteButtonPressed(_ sender: UIButton) {
if allSelected.count > 0 {
for element in allSelected {
removeSelectedCells(i: element.item)
}
}
}
func removeSelectedCells(i: Int) {
self.myHobbiesArray.remove(at: i) // This is what Xcode shows as the crash on the fatal error.
let indexPath = NSIndexPath(row: i, section: 0)
self.myHobbiesCV.deleteItems(at: NSArray(object: indexPath) as! [IndexPath])
//self.myHobbiesCV.performBatchUpdates({
// self.myHobbiesCV.deleteItems(at: NSArray(object: indexPath) as! [IndexPath])
//}) { (true) in
// self.myHobbiesCV.reloadData()
//}
}
如果您能提供任何帮助来处理从集合视图中删除多个单元格,我们将不胜感激。如果您需要更多信息,我很乐意澄清。
使用 SO 答案 ,您应该能够从 indexPaths 的 allSelected
数组中获取索引,然后一次性从 myHobbiesArray
中删除索引。
@IBAction func deleteButtonPressed(_ sender: UIButton) {
let indices = allSelected.map{ [=10=].item }
myHobbiesArray = myHobbiesArray.enumerated().flatMap { indices.contains([=10=].0) ? nil : [=10=].1 }
self.myHobbiesCV.deleteItems(at: allSelected)
}
我有一个带有非常简单数据源的 UICollectionView。它只是一个以编程方式更新的字符串数组。使用此 UICollectionView,我可以点击 select 多个单元格 - 然后可以使用删除按钮删除所有 selected 单元格。很简单,除了我有时会遇到致命错误:索引超出范围。
通过在另一个名为 "All Hobbies" 的集合视图中点击单元格以编程方式添加单元格 - 在 "All Hobbies" CV 中点击和 select 的任何单元格都会添加到 "My Hobbies." 我通过将点击的单元格的值附加到控制 My Hobbies CV 的数组来做到这一点。
问题
- 根据我 select 在我的爱好中的哪些单元格,删除按钮(下面的代码)有时会删除它们,或者有时会崩溃并出现致命错误:索引超出范围。它似乎不会在第一次删除时崩溃(如果有帮助的话。)
- 如果我的爱好中的单元格确实删除了,当我点击 "All Hobbies" 中的更多单元格时 - 它们添加到 "My Hobbies" 为 UIColor.red(表示它们是 selected。)(然后在我按下 delete btn 后会迟到崩溃。)单元格应添加为黄色。
我的数据似乎在删除后没有更新,当我再次尝试删除时,索引超出了范围。但是我在我的代码中找不到导致这种情况发生的问题(如果这确实是问题...)
Class 等级
let allHobbiesArray = ["Skiing", "Jogging", "Bicycling", "Basketball", "Cricket", "Being a Couch Potato", "Skiing", "Jogging", "Bicycling", "Basketball", "Cricket", "Being a Couch Potato", "Skiing", "Jogging", "Bicycling", "Basketball", "Cricket", "Being a Couch Potato", "Skiing", "Jogging", "Bicycling", "Basketball", "Cricket", "Being a Couch Potato"]
var myHobbiesArray = [String]()
var allSelected = [IndexPath]()
数据源
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView == allHobbiesCV {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ALL", for: indexPath) as! AllHobbiesCell
cell.allHobbiesLabel.text = allHobbiesArray[indexPath.row]
return cell
}
else {
let cell = myHobbiesCV.dequeueReusableCell(withReuseIdentifier: "MY", for: indexPath) as! MyHobbiesCell
cell.myHobbiesLabel.text = myHobbiesArray[indexPath.row]
return cell
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionView == allHobbiesCV {
return allHobbiesArray.count
}
else {
return myHobbiesArray.count
}
}
代表
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if collectionView == allHobbiesCV {
let cell = allHobbiesCV.cellForItem(at: indexPath) as! AllHobbiesCell
myHobbiesArray.append(allHobbiesArray[indexPath.row])
myHobbiesCV.reloadData()
for i in 0..<allSelected.count {
self.myHobbiesCV.selectItem(at: allSelected[i], animated: false, scrollPosition: [])
}
}
else {
let cell = myHobbiesCV.cellForItem(at: indexPath) as! MyHobbiesCell
cell.backgroundColor = UIColor.red // Red background to show that it's selected
// Store all of the selected cells in allSelected
allSelected = self.myHobbiesCV.indexPathsForSelectedItems!
}
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
if collectionView == allHobbiesCV {
let cell = allHobbiesCV.cellForItem(at: indexPath) as! AllHobbiesCell
cell.backgroundColor = UIColor.yellow
}
else {
let cell = myHobbiesCV.cellForItem(at: indexPath) as! MyHobbiesCell
cell.backgroundColor = UIColor.yellow
// update allSelected after deselect
allSelected = self.myHobbiesCV.indexPathsForSelectedItems!
}
}
正在删除单元格
@IBAction func deleteButtonPressed(_ sender: UIButton) {
if allSelected.count > 0 {
for element in allSelected {
removeSelectedCells(i: element.item)
}
}
}
func removeSelectedCells(i: Int) {
self.myHobbiesArray.remove(at: i) // This is what Xcode shows as the crash on the fatal error.
let indexPath = NSIndexPath(row: i, section: 0)
self.myHobbiesCV.deleteItems(at: NSArray(object: indexPath) as! [IndexPath])
//self.myHobbiesCV.performBatchUpdates({
// self.myHobbiesCV.deleteItems(at: NSArray(object: indexPath) as! [IndexPath])
//}) { (true) in
// self.myHobbiesCV.reloadData()
//}
}
如果您能提供任何帮助来处理从集合视图中删除多个单元格,我们将不胜感激。如果您需要更多信息,我很乐意澄清。
使用 SO 答案 allSelected
数组中获取索引,然后一次性从 myHobbiesArray
中删除索引。
@IBAction func deleteButtonPressed(_ sender: UIButton) {
let indices = allSelected.map{ [=10=].item }
myHobbiesArray = myHobbiesArray.enumerated().flatMap { indices.contains([=10=].0) ? nil : [=10=].1 }
self.myHobbiesCV.deleteItems(at: allSelected)
}