我尝试删除多个(以编程方式添加)单元格后,CollectionView崩溃

时间:2017-03-14 00:38:10

标签: swift crash uicollectionview uicollectionviewcell

我有一个带有非常简单数据源的UICollectionView。它只是一个以编程方式更新的字符串数组。使用此UICollectionView,我可以点击选择多个单元格 - 然后可以使用“删除”按钮删除所有选定的单元格。很简单,除了我有时会出现致命错误:索引超出范围。

通过在另一个名为" All Hobbies" - 无论是哪种细胞都可以使用在"所有爱好"中选择简历被添加到"我的爱好。"我这样做是通过将tapped cell的值附加到控制My Hobbies CV的数组。

问题

  1. 根据我在My Hobbies中选择的单元格,删除按钮(下面的代码)有时会删除它们,或者有时会因致命错误而崩溃:索引超出范围。它在第一次删除时似乎没有崩溃(如果有帮助的话。)
  2. 如果我的爱好中的细胞实际上是删除,当我在"所有爱好"中点击更多细胞时 - 他们加入了我的爱好"作为UIColor.red(表示它们已被选中。)(然后在按下删除btn后会迟到。)单元格应添加为黄色。
  3. 似乎我的数据在删除后没有更新,当我再次尝试删除时,索引超出范围。但是,我无法在我的代码中找到导致这种情况发生的问题(如果这确实是问题......)

    班级

    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()
        //}
    }
    

    非常感谢任何帮助处理从集合视图中删除多个单元格。如果您需要更多信息,我将很乐意澄清。

1 个答案:

答案 0 :(得分:1)

使用SO回答here,您应该能够从allSelected indexPaths数组中获取索引,然后立即从myHobbiesArray中删除所有索引。

@IBAction func deleteButtonPressed(_ sender: UIButton) {
    let indices = allSelected.map{ $0.item } 
    myHobbiesArray = myHobbiesArray.enumerated().flatMap { indices.contains($0.0) ? nil : $0.1 }
    self.myHobbiesCV.deleteItems(at: allSelected)
}