Swift - 切换CollectionView单元格以切换数组中的项目

时间:2017-03-27 21:46:49

标签: ios swift xcode

我有两个CollectionView。一个CollectionView(allHobbiesCV)预先填充了您可以选择的爱好。另一个CollectionView(myHobbiesCV)是空的,但是如果你点击allHobbiesCV中的一个爱好,它会被添加到myHobbiesCV中。这一切都很有效。

我希望tapped allHobbiesCV单元格切换到selected,它会将爱好添加到myHobbiesCV,然后如果用户再次在allHobbiesCV中点击相同的选定单元格,它会从myHobbiesCV中删除该爱好。基本上是一个切换添加/删除。

有两点需要注意:

  1. 用户可以在myHobbiesCV中手动选择爱好,然后点击[删除爱好]按钮。
  2. 爱好将按季节排序,因此所有爱好阵营将有4种不同的数据集(冬季,春季,夏季,秋季)。根据用户点击的季节(ViewController)。他们可以根据需要从每个单元中选择多个/几个单元格。
  3. 问题:

    除了第一个单元格之外,我正在崩溃。如果我选择allHobbiesCV中的第一个单元格,我可以再次选择它,它将从myHobbiesCV中删除它。如果我再次选择相同的单元格(切换它),我崩溃了。如果我选择除第一个之外的任何其他单元格,我会崩溃。

    *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to delete item 7 from section 0 which only contains 3 items before the update'
    

    班级

    // Winter Hobbies
    let allHobbiesArray = ["Skiing", "Snowboarding", "Drinking Bourbon", "Snow Shoeing", "Snowmobiling", "Sledding", "Shoveling Snow", "Ice Skating"]
    var myHobbiesArray = [String]()
    var allSelected = [IndexPath]()
    var didSelectIPArray = [IndexPath]()
    

    数据来源

    extension ViewController: UICollectionViewDataSource {
    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.item]
    
            if cell.isSelected {
                cell.backgroundColor = UIColor.green
            }
            else {
                cell.backgroundColor = UIColor.yellow
            }
    
            return cell
        }
    
        else {
            let cell = myHobbiesCV.dequeueReusableCell(withReuseIdentifier: "MY", for: indexPath) as! MyHobbiesCell
            cell.myHobbiesLabel.text = myHobbiesArray[indexPath.item]
    
            if cell.isSelected {
                cell.backgroundColor = UIColor.red
            }
            else {
                cell.backgroundColor = UIColor.yellow
            }
    
    
            return cell
        }
    
    
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        if collectionView == allHobbiesCV {
            return allHobbiesArray.count
        }
        else {
            return myHobbiesArray.count
        }
    
    }
    
    }
    

    代表

    extension ViewController: UICollectionViewDelegate {
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    
    
        if collectionView == allHobbiesCV {
            if myHobbiesArray.count <= 6
                self.allSelected = []
    
                didSelectIPArray.append(indexPath) // Store the selected indexPath in didSelectIPArray
    
                myHobbiesArray.insert(allHobbiesArray[indexPath.item], at: 0)
                let allHobbiesCell = allHobbiesCV.cellForItem(at: indexPath) as! AllHobbiesCell
                allHobbiesCell.backgroundColor = UIColor.green
    
                // Store all of the selected cells in an array
                didSelectIPArray.append(indexPath) 
    
                myHobbiesCV.reloadData()
            }
        }
    
    
        else {
            let cell = myHobbiesCV.cellForItem(at: indexPath) as! MyHobbiesCell
            cell.backgroundColor = UIColor.red
            allSelected = self.myHobbiesCV.indexPathsForSelectedItems!
        }
    
    
    }
    
    // Deselecting selected cells
    func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
    
        if collectionView == allHobbiesCV {
    
            // Yellow is the unselected cell color. So let's change it back to yellow.
            let allHobbiesCell = allHobbiesCV.cellForItem(at: indexPath) as! AllHobbiesCell
            allHobbiesCell.backgroundColor = UIColor.yellow
    
            // Remove (toggle) the cells. This is where I am stuck/crashing.
            let indices = didSelectIPArray.map{ $0.item }
            myHobbiesArray = myHobbiesArray.enumerated().flatMap { indices.contains($0.0) ? nil : $0.1 }
            self.myHobbiesCV.deleteItems(at: didSelectIPArray)
    
            myHobbiesCV.reloadData()
    
            didSelectIPArray.remove(at: indexPath.item) // Remove the deselected indexPath from didSelectIPArray
        }
    
        else { // MyHobbies CV
            let cell = myHobbiesCV.cellForItem(at: indexPath) as! MyHobbiesCell
            cell.backgroundColor = UIColor.yellow
    
            // Store the selected cells to be manually deleted.
            allSelected = self.myHobbiesCV.indexPathsForSelectedItems!
    
        }
    }
    }
    

    删除按钮

    @IBAction func deleteButtonPressed(_ sender: UIButton) {
        for item in didSelectIPArray {
            self.allHobbiesCV.deselectItem(at: item, animated: false) // Try deselecting the deleted items in allHobbiesCV... This is crashing.
        }
    }
    

    问题是我如何尝试在didDeselect中切换allHobbiesCV单元格。我的方法在didSelectIPArray中保存选定的单元格是否正确?

    如果需要,我很乐意提供进一步的见解。非常感谢你的朋友!

1 个答案:

答案 0 :(得分:1)

不需要所有mapflatmap内容。您只需从选定的爱好数组中删除对象:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    if collectionView == allHobbiesCV {
        if myHobbiesArray.count <= 6
            self.allSelected = []
            myHobbiesArray.insert(allHobbiesArray[indexPath.item], at: 0)

            let allHobbiesCell = allHobbiesCV.cellForItem(at: indexPath) as! AllHobbiesCell
            allHobbiesCell.backgroundColor = UIColor.green

            myHobbiesCV.insertItems(at: [IndexPath(item: 0, section: 0)])
        }
    } else {
        let cell = myHobbiesCV.cellForItem(at: indexPath) as! MyHobbiesCell
        cell.backgroundColor = UIColor.red
        allSelected = self.myHobbiesCV.indexPathsForSelectedItems!
    }
}

func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {

    if collectionView == allHobbiesCV {

        // Yellow is the unselected cell color. So let's change it back to yellow.
        let allHobbiesCell = allHobbiesCV.cellForItem(at: indexPath) as! AllHobbiesCell
        allHobbiesCell.backgroundColor = UIColor.yellow

        let hobby = allHobbiesArray[indexPath.item]

        if let index = myHobbiesArray.index(of:hobby) {
             myHobbiesArray.remove(at: index)
             myHobbiesCV.deleteItems(at: [IndexPath(item: index, section:0)])
        }
    } else { // MyHobbies CV
        let cell = myHobbiesCV.cellForItem(at: indexPath) as! MyHobbiesCell
        cell.backgroundColor = UIColor.yellow

        // Store the selected cells to be manually deleted.
        allSelected = self.myHobbiesCV.indexPathsForSelectedItems!

    }
}