【问题标题】:Cells do not load using UITableVIewDiffableDataSource不使用 UITableVIewDiffableDataSource 加载单元格
【发布时间】:2020-02-22 09:24:15
【问题描述】:

我正在尝试使用新的 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 处创建一个符号断点,以便在调试器中捕获它并查看导致这种情况发生的原因,因此如果可能的话,您可以完全避免此操作,或者将其推迟到表格视图添加到窗口中。表视图:;层 = ;内容偏移:{0, 0};内容大小:{414, 0};调整内容插入:{0, 0, 0, 0};数据源:TtGC5UIKit29UITableViewDiffableDataSourceOC11FXTMproject26CurrencyListViewControllerP10$107a9eb7c7SectionSS:0x600002960ca0>>

【问题讨论】:

    标签: ios swift tableview


    【解决方案1】:

    首先,您的代码中有一个很大的设计错误。

    使用UITableViewDiffableDataSource 停止考虑索引路径和数据源数组。而是考虑数据源items

    setupDataSource 中,您始终从数据源数组 currencyPairsArray 获取行的模型项,无论您是否要显示过滤后的数据。忘记currencyPairsArray 和索引路径。利用闭包中代表 item 的第三个参数。

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

    并且永远不要在使用 UITableViewDiffableDataSource 时调用 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)
            }
        }
    

    【讨论】:

    • 效果很好!我明白这件事现在应该如何工作了!谢谢。
    猜你喜欢
    • 2021-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-16
    • 2020-06-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多