Ячейки не загружаются с использованием UITableVIewDiffableDataSource - PullRequest
0 голосов
/ 22 февраля 2020

Я пытаюсь реализовать табличное представление с новым API DiffableDataSource, но ячейки просто не загружаются:

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 было приказано расположить свои видимые ячейки и другое содержимое, не находясь в иерархии представлений (табличное представление или одно из его суперпредставлений не было добавлено в окно). Это может привести к ошибкам, заставляя представления внутри табличного представления загружаться и выполнять компоновку без точной информации (например, границ табличного представления, сбора признаков, полей макета, вставок в безопасной области и т. Д. c), а также приведет к ненужным потерям производительности из-за дополнительные макеты проходит. Создайте символьную c точку останова в UITableViewAlertForLayoutOutsideViewHierarchy, чтобы перехватить это в отладчике и посмотреть, что вызвало это, чтобы вы могли вообще избежать этого действия, если это возможно, или отложить его, пока представление таблицы не будет добавлено в окно. Вид таблицы:; слой =; contentOffset: {0, 0}; contentSize: {414, 0}; AdjustContentInset: {0, 0, 0, 0}; источник данных: <<em> TtGC5UIKit29UITableViewDiffableDataSourceOC11FXTMproject26CurrencyListViewControllerP10 $ 107a9eb7c7SectionSS : 0x600002960ca0 >>

1 Ответ

1 голос
/ 22 февраля 2020

Прежде всего, в вашем коде есть большая ошибка проектирования.

С UITableViewDiffableDataSource перестаньте думать в индексных путях и массивах источников данных. Вместо этого подумайте в источнике данных items .

В 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() при использовании UITableViewDiffableDataSource, что, скорее всего, является причиной вашей проблемы.

Заменить

    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)
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...