更新数据源并调用reloadData之后,cellForItem

时间:2019-12-06 22:31:10

标签: swift uicollectionview

我有一个收集视图,该视图由数据源填充,该数据源是协议类型的数组。数据源在我的视图控制器SomeViewController中声明。

var dataSource = [SomeProtocol]()

我已将数据源和集合视图的委托都设置为self

override func viewDidLoad() {
    super.viewDidLoad()
    someDataSourcePopulationMethod()
    collectionView.dataSource = self
    collectionView.delegate = self
}

数据源方法以SomeViewController的扩展名实现。

extension SomeViewController: UICollectionViewDataSource {

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return dataSource.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let item = dataSource[indexPath.row]
        switch item.type {
            case .typeA:
                // Dequeue cell and configure
                return cellTypeA
            case .typeB:
                // Dequeue cell and configure
                return cellTypeB
        }
    }

}

一切正常。直到我从数据源数组中过滤出某种类型并重新加载数据。

func filterDataAndReload() {
    dataSource = dataSource.filter { !($0 is TypeA) }
    collectionView.reloadData()
}

比方说,数据源中的第一项最初是TypeA的项。此代码应删除第一项(以及TypeA的所有其他项),并更新集合视图以仅显示TypeB的项。

但是它不起作用。我仍然看到TypeA的单元格。

我已经检查了数据源是否确实已被过滤。在filter方法上设置断点时,可以看到数据源仅包含TypeB项。

但是当我在cellForItem方法中放置一个断点时,我发现数据源根本没有被更新。

为什么会这样?

没有异步发生,因此我不需要分派到主线程。 (尽管我已经尝试过了。)

我也尝试过清理项目并重建。

编辑:

我做了更多的调查。

如果在调用filter方法时TypeA单元格可见,则它们不会改变。实际上,它们代替了应该存在的TypeB单元。我可以滚动离开它们,然后向后滚动,但它们仍然没有改变。

但是,如果我滚动离开TypeA单元,然后使用filter方法,当我滚动回到TypeA单元最初所在的位置时,它们将不再存在。

1 个答案:

答案 0 :(得分:0)

尝试类似这样的方法。我用调用过滤器功能的按钮对其进行了测试,它们可以正常工作。如果点击“过滤字符串”按钮,则该集合将删除所有Int值并仅显示数字字符串。 “过滤器整数”按钮也是如此。

import UIKit

class ViewController: UIViewController {

    var dataSource: [Any] = []

    @IBAction func filterStringsBtnTap(_ sender: UIButton) {
        filterStrings()
    }

    @IBAction func filterIntsBtnTap(_ sender: UIButton) {
        filterInts()
    }

    @IBAction func resetDataBtnTap(_ sender: UIButton) {
        dataSource = [1,2,3,"four","five","six",7,8,"nine","ten"]
        collectionView.reloadData()
    }

    @IBOutlet weak var collectionView: UICollectionView!

    override func viewDidLoad() {
        super.viewDidLoad()
        populateData()
        collectionView.dataSource = self
        collectionView.delegate = self
    }

    func populateData() {
        dataSource = [1,2,3,"four","five","six",7,8,"nine","ten"]
    }

    func filterStrings() {
        dataSource = dataSource.filter { $0 is String }
        collectionView.reloadData()
    }

    func filterInts() {
        dataSource = dataSource.filter { $0 is Int }
        collectionView.reloadData()
    }

}

extension ViewController: UICollectionViewDataSource, UICollectionViewDelegate {

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return dataSource.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        let item = dataSource[indexPath.row]

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "myCell", for: indexPath) as! MyCollectionViewCell

        switch item {
        case let stringItem as String:
            cell.myCellLabel.text = " \(stringItem) "
            return cell
        case let numberItem as Int:
            cell.myCellLabel.text = " \(numberItem) "
            return cell
        default:
            print("This should not happen")
            return cell
        }

    }

}

希望这会有所帮助。祝你好运!