Mam następujący kod MVVM-C + RxSwift.
Problem polega na tym, że TableView nie odbiera żadnych sygnałów. Kiedy ja debuguj wyniki Widzę, że wywołanie API zwraca to, co powinno, tablica objects
jest wypełniona obiektami, ale widok tabeli nie pokazuje żadnych wyników. Oto dane wyjściowe konsoli:
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([])
Czy to może być sam widok tabeli? Może zła niestandardowa konfiguracja komórki?
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 odpowiedź
- Korzystając z
flatMap
, nie chcesz tworzyć zagnieżdżonych subskrypcji. StworzyszObservable
, który zwróci oczekiwany wynik, a flatMap zajmie się jego zasubskrybowaniem. W obecnym stanie rzeczysearchSomething
zawsze zwróci pustą tablicę, ponieważObservable.from(optional: objects)
zostanie wywołane, zanim żądanie będzie miało szansę się zakończyć. - Od wersji 10.0 Moya dostawca anuluje utworzone żądania po cofnięciu alokacji. Tutaj zostanie on cofnięty, gdy wykonanie zakończy się
searchSomething
, stąd żądanie sieciowe nie będzie miało czasu na zakończenie. Przeniesienie deklaracji dostawcy na poziom modelu widoku rozwiązuje ten problem.
Oto searchSomething(query: String) -> Observable<[Object]>
przepisany.
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)
}
}
Zamiast wykonywać transformację w subskrypcji, robi się to w map
, które będzie wywoływane dla każdego zdarzenia next
, przekazując wartość związaną ze zdarzeniem.
Podobne pytania
Nowe pytania
ios
iOS to mobilny system operacyjny działający na urządzeniach Apple iPhone, iPod touch i iPad. Użyj tego tagu [ios] w przypadku pytań związanych z programowaniem na platformie iOS. Użyj powiązanych tagów [objective-c] i [swift] w przypadku problemów specyficznych dla tych języków programowania.