Драйвер RxSwift - проблемы с обнуляемыми фреймами ячеек UITableView и фоновым представлением - PullRequest
0 голосов
/ 28 ноября 2018

A UITableView снабжается данными из ViewModel с RxSwift Driver.

Вариант использования - это простой текстовый поиск - когда пользователь вводит строку в SearchBar API возвращает результаты или нет результатов.Если результатов нет, драйвер возвращает пустой массив.

Проблема в том, что когда результатов нет, а затем поисковый запрос обновляется, поэтому теперь есть результаты, для фреймов ячеек в табличном представлении по умолчанию задано значение(0, 0, 0, 44) - и, таким образом, вообще не показаны.Я устанавливаю начальный backgroundView для UITableView, то есть nilled, когда есть результаты из запроса в части .do {}.Ячейки внезапно отображаются, когда я прокручиваю вниз, а затем снова вверх, но почему-то изначально они покрываются фоновым представлением, которое должно быть nil.

Это происходит только при переходе от пустого результата кнепустой результат.Если в ячейках есть результаты, изменение строки запроса и отображение новых результатов работает нормально.

Что может привести к обнулению кадров ячеек и как правильно очистить результаты UITableView (и показать «Нет»).Сообщение о результатах в UITableView.backgroundView вместо), если Driver испускает пустой набор результатов?

ViewModel.swift

var searchText = PublishSubject<String>()

private func getData() -> Driver<[Item]> {
    return self.searchText
        .filter({ (query) -> Bool in
            return query.count > 0
        })
        .asObservable()
        .throttle(0.2, scheduler: MainScheduler.instance)
        .distinctUntilChanged()
        .flatMapLatest(searchAPI)
        .asDriver(onErrorJustReturn: [])

}

ViewController.swift

var viewModel: SearchViewModel!

var tableView: UITableView!
let searchController = UISearchController(searchResultsController: nil)
var searchBar: UISearchBar { return searchController.searchBar }


override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

override func viewDidLoad() {
    super.viewDidLoad()

    setupUI()
    setupBindings()
}

private func setupUI() {
    tableView = UITableView(frame: self.view.frame)
    tableView.register(SearchResultCell.self, forCellReuseIdentifier: "SearchResultCell")
    tableView.rowHeight = 56
    tableView.tableHeaderView = searchBar
    tableView.separatorStyle = .none
    tableView.keyboardDismissMode = .onDrag

    tableView.delegate = nil
    tableView.dataSource = nil
    view.addSubview(tableView)

    showMessage(.initial)

    configureSearchController()
    searchController.searchBar.searchBarStyle = .minimal
}


private func showMessage(_ type: SearchMessage) {
    let rect = CGRect(origin: CGPoint(x: 0,y :0), size: CGSize(width: self.view.bounds.size.width, height: self.view.bounds.size.height))
    let emptyMessageLabel = UILabel(frame: rect)

    switch type {

    case .initial:
        emptyMessageLabel.text = "Try searching bla bla"

    case .noResult:
        emptyMessageLabel.text = "No results found.\nTry searching again"
    }

    tableView.backgroundView = emptyMessageLabel;
}


extension SearchViewController {
    private func setupBindings() {
        viewModel.data
           .do(onNext: { [weak self] items in
                guard let self = self else { return }
                self.tableView.backgroundView = nil
                if items.count == 0 {
                   self.showMessage(.noResult)
                }
            })
            .drive(tableView.rx.items(cellIdentifier: "SearchResultCell", cellType: SearchResultCell.self)) { row, item, cell in
                cell.label.text = item.title
                do {
                    try _ = cell.imageView.kf.rx.setImage(with: item.imageUrl.asURL()).subscribe()
                } catch(let error) {
                    cell.imageView.image = UIImage.init(named: "DefaultImage")
                }
            }
            .disposed(by: disposeBag)
    }
}

SearchResultCell.swift

class SearchResultCell: UITableViewCell {

    var nameLabel: UILabel!
    var imageView: UIImageView!

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        setupUI()
    }

    private func setupUI() {
        clipsToBounds = true
        autoresizesSubviews = false

        nameLabel = UILabel()
        imageView = UIImageView(image: nil)
        imageView.contentMode = .scaleAspectFit

        contentView.addSubview(nameLabel)
        contentView.addSubview(imageView)

        nameLabel.textColor = .darkGray
        nameLabel.font = UIFont.systemFont(ofSize: 15)
    }
...