我试图用新的DiffableDataSource api实现表视图,但是单元格根本不加载:
var tableView = UITableView()
var currencyPairsArray = [String]()
lazy var fetcher = NetworkDataFetcher()
lazy var searchText = String()
lazy var searchArray = [String]()
lazy var searchController: UISearchController = {
let controller = UISearchController(searchResultsController: nil)
controller.hidesNavigationBarDuringPresentation = false
controller.obscuresBackgroundDuringPresentation = false
controller.searchBar.delegate = self
return controller
}()
fileprivate var dataSource : UITableViewDiffableDataSource<Section, String>!
var searchBarIsEmpty: Bool {
return searchController.searchBar.text?.isEmpty ?? true
}
override func viewDidLoad() {
super.viewDidLoad()
setupVC()
setupTableView()
setupDataSource()
performSearch(with: nil)
fetcher.fetchCurrencyPairs { [weak self] pairsArray in
self?.currencyPairsArray.append(contentsOf: pairsArray)
DispatchQueue.main.async {
self?.tableView.reloadData()
}
}
//tableView.reloadData()
// Do any additional setup after loading the view.
}
func setupVC() {
view.backgroundColor = .white
view.addSubview(tableView)
navigationItem.title = "Currency pairs"
navigationItem.searchController = searchController
navigationItem.hidesSearchBarWhenScrolling = false
}
func setupTableView() {
tableView.delegate = self
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.pinToSuperView()
tableView.register(UINib(nibName: "CurrencyPairCell", bundle: nil), forCellReuseIdentifier: CurrencyPairCell.reuseIdentifier)
}
func setupDataSource() {
dataSource = UITableViewDiffableDataSource<Section, String>(tableView: tableView, cellProvider: { [weak self] (tableView, indexPath, _) -> UITableViewCell? in
let cell = tableView.dequeueReusableCell(withIdentifier: CurrencyPairCell.reuseIdentifier, for: indexPath) as! CurrencyPairCell
cell.delegate = self
let pair = self?.currencyPairsArray[indexPath.row].formattedPair()
cell.currencyPairLabel.text = pair
cell.currencyPair = self?.currencyPairsArray[indexPath.row] ?? ""
return cell
})
}
func performSearch(with filter: String?) {
var snapshot = NSDiffableDataSourceSnapshot<Section, String>()
if let filter = filter {
let filteredPairs = currencyPairsArray.filter {$0.contains(filter)}
snapshot.appendSections([.main])
snapshot.appendItems(filteredPairs, toSection: .main)
dataSource.apply(snapshot, animatingDifferences: true)
} else {
let pairs = currencyPairsArray.sorted()
snapshot.appendSections([.main])
snapshot.appendItems(pairs, toSection: .main)
dataSource.apply(snapshot)
}
}
}
extension CurrencyListViewController: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
performSearch(with: searchText)
}
}
extension CurrencyListViewController {
fileprivate enum Section: Hashable {
case main
}
}此外,我还收到了xcode的警告:
TableView只警告一次: UITableView被告知在不处于视图层次结构的情况下布局其可见的单元格和其他内容(表视图或其超级视图之一尚未添加到窗口中)。这可能会导致错误,因为强制表视图中的视图加载和执行布局而没有精确的信息(例如表视图边界、特征收集、布局边距、安全区域嵌入等),并且还会由于额外的布局传递而造成不必要的性能开销。在UITableViewAlertForLayoutOutsideViewHierarchy上设置一个符号断点,以便在调试器中捕捉到这一点,并查看导致这种情况发生的原因,这样,如果可能的话,您可以完全避免此操作,或者将其推迟到将表视图添加到窗口之后。表视图:;layer =;contentOffset:{0,0};contentSize:{414,0};adjustedContentInset:{0,0,0};dataSource: dataSource 0x600002960ca0>>
发布于 2020-02-22 10:12:39
首先,代码中存在一个很大的设计错误。
使用UITableViewDiffableDataSource,停止在索引路径和数据源数组中进行思考。相反,在数据源中考虑项。
在setupDataSource中,您总是从数据源数组currencyPairsArray获得行的模型项,而不管您是否要显示筛选过的数据。忘记currencyPairsArray和索引路径。利用闭包中的第三个参数,它表示项。
func setupDataSource() {
dataSource = UITableViewDiffableDataSource<Section, String>(tableView: tableView, cellProvider: { [weak self] (tableView, _, pair) -> UITableViewCell? in
let cell = tableView.dequeueReusableCell(withIdentifier: CurrencyPairCell.reuseIdentifier, for: indexPath) as! CurrencyPairCell
cell.delegate = self
cell.currencyPairLabel.text = pair.formattedPair()
cell.currencyPair = pair
return cell
})
}若要消除警告,请执行第一次重新加载数据,而不使用动画。向performSearch添加一个布尔参数。与其检查nil,不如检查空字符串
func performSearch(with filter: String, animatingDifferences: Bool = true) {
var snapshot = NSDiffableDataSourceSnapshot<Section, String>()
let pairs : [String]
if filter.isEmpty {
pairs = currencyPairsArray.sorted()
} else {
pairs = currencyPairsArray.filter {$0.contains(filter)}
}
snapshot.appendSections([.main])
snapshot.appendItems(pairs, toSection: .main)
dataSource.apply(snapshot, animatingDifferences: animatingDifferences)
}当使用时,从不调用tableView.reloadData(),这很可能是引发问题的原因。
替换
performSearch(with: nil)
fetcher.fetchCurrencyPairs { [weak self] pairsArray in
self?.currencyPairsArray.append(contentsOf: pairsArray)
DispatchQueue.main.async {
self?.tableView.reloadData()
}
}使用
fetcher.fetchCurrencyPairs { [weak self] pairsArray in
self?.currencyPairsArray.append(contentsOf: pairsArray)
DispatchQueue.main.async {
self?.performSearch(with: "", animatingDifferences: false)
}
}https://stackoverflow.com/questions/60350719
复制相似问题