我有一个收集视图,该视图由数据源填充,该数据源是协议类型的数组。数据源在我的视图控制器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单元最初所在的位置时,它们将不再存在。
答案 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
}
}
}
希望这会有所帮助。祝你好运!