Tableview не получает сигналы от водителя - PullRequest
0 голосов
/ 14 ноября 2018

У меня есть следующий код MVVM-C + RxSwift.

Проблема в том, что TableView не получает никаких сигналов. Когда я Отладка результатов. Я вижу, что вызов API возвращает то, что он должен, массив objects заполнен объектами, но табличное представление не показывает никаких результатов. Вот вывод консоли:

2018-11-13 16:12:08.107: searchText -> Event next(qwerty)
Search something: qwerty
2018-11-13 16:12:08.324: viewModel.data -> Event next([])

Может быть, это само представление таблицы? Может быть, неправильная настройка пользовательских ячеек?

ViewController.swift:

    tableView = UITableView(frame: self.view.frame)
    tableView.delegate = nil
    tableView.dataSource = nil
    tableView.register(SearchResultCell.self, forCellReuseIdentifier: "SearchResultCell")

    viewModel.data
        .debug("viewModel.data", trimOutput: false)
        .drive(tableView.rx.items(cellIdentifier: "SearchResultCell")) { row, object, cell in

            cell.name.text = object.name
            cell.something.text = object.something
        }
        .disposed(by: disposeBag)

ViewModel.swift:

let disposeBag = DisposeBag()
var searchText = BehaviorRelay(value: "something to search for")

lazy var data: Driver<[Object]> = {
    return self.searchText.asObservable()
        .debug("searchText", trimOutput: false)
        .throttle(0.3, scheduler: MainScheduler.instance)
        .distinctUntilChanged()
        .flatMapLatest(searchSomething)
        .asDriver(onErrorJustReturn: [])
}()

func searchSomething(query: String) -> Observable<[Object]> {

    print("Search something: \(query)")

    let provider = MoyaProvider<APIService>()

    var objects = [Object]()

    provider.rx.request(.search(query: query)).subscribe { event in
        switch event {
        case let .success(response):
            do {
                let responseJSON: NSDictionary = try (response.mapJSON() as? NSDictionary)!
                objects = self.parse(json: responseJSON["results"] as Any)

            } catch(let error) {
                print(error)
            }

            break
        case let .error(error):
            print(error)
            break
        }
    }
    .disposed(by: disposeBag)

    let result: Observable<[Object]> = Observable.from(optional: objects)

    return result
}

1 Ответ

0 голосов
/ 14 ноября 2018
  • При использовании flatMap вы не хотите создавать вложенные подписки. Вы создадите Observable, который возвращает ожидаемый результат, и flatMap позаботится о том, чтобы подписаться на него. В текущем состоянии searchSomething всегда будет возвращать пустой массив, так как Observable.from(optional: objects) будет вызываться до того, как запрос сможет завершиться.
  • Начиная с версии 10.0 Moya, провайдер отменяет запросы, созданные при освобождении . Здесь он будет освобожден, когда выполнение завершится searchSomething, следовательно, сетевой запрос не успеет завершиться. Перемещение декларации провайдера на уровень модели представления решает эту проблему.

Вот searchSomething(query: String) -> Observable<[Object]> переписано.

let provider = MoyaProvider<APIService>()

func searchSomething(query: String) -> Observable<[Object]> {

    print("Search something: \(query)")

    return provider.rx.request(.search(query: query)).map { (response) -> [Object] in
        let responseJSON: NSDictionary = try (response.mapJSON() as? NSDictionary)!

        return self.parse(json: responseJSON["results"] as Any)
    }
}

Вместо преобразования в подписке это делается в map, который будет вызываться для каждого события next, которому передается значение, связанное с событием.

...