2016-04-28 9 views
6

Obecnie używam Moya do wysyłania żądań sieci. Zaimplementowałem następujące elementy z jednego z przykładowych projektów: @https://github.com/DroidsOnRoids/RxSwiftExamples#tutorialsObsługa błędu sieciowego w połączeniu z powiązaniem z tableView (Moya, RxSwift, RxCocoa)

Poniżej skonfigurowałem wyszukiwanie w restauracji tak, aby po wprowadzeniu tekstu pojawiła się nowa prośba.

var restaurantSearch: Observable<(String)> { 
    return searchBar 
     .rx_text 
     .throttle(0.5, scheduler: MainScheduler.instance) 
     .distinctUntilChanged() 
} 

mam metodę, która zwraca obserwowalne typu [restauracja]

func restaurants() -> Observable<[Restaurant]> { 
    return restaurantSearch 
     .observeOn(MainScheduler.instance) 
     .flatMapLatest { postcode -> Observable<[Restaurant]?> in 
      return self.getRestaurants(postcode, cuisine: "", restaurantName: "") 
     }.replaceNilWith([]) 
} 

internal func getRestaurants(postcode: String, cuisine: String, restaurantName: String) -> Observable<[Restaurant]?> { 
    return self.justEatProvider 
     .request(.Restaurant(postcode, cuisine, restaurantName)) 
     .debug() 
     .mapArrayOptional(Restaurant.self, keyPath: "Restaurants") 
} 

wzywam tę metodę i wiążące go do Tableview tak:

func setupRx() { 

    api = JustEatApi(provider: provider, restaurantSearch: restaurantSearch) 

    api 
     .restaurants() 
     .bindTo(tableView.rx_itemsWithCellIdentifier("RestaurantTableViewCell", cellType: RestaurantTableViewCell.self)) { (row, element, cell) in 
      cell.restaurant = element 
     } 
     .addDisposableTo(disposeBag) 
} 

Jest Dobrze pracować. Jeśli wprowadzę kod pocztowy, wyszukiwanie i tableView zostaną wypełnione.

Jeśli wyłączę internet i spróbuję zmienić kod pocztowy, tableView pozostanie bez zmian. Jednak kiedy przewijać się zawiesi moją aplikację z następującymi zasadami:

@noreturn func rxFatalError(lastMessage: String) { 
    // The temptation to comment this line is great, but please don't, it's for your own good. The choice is yours. 
    fatalError(lastMessage) 
} 

Także jeśli nie przejść, ale zamiast po prostu zawrócić w internecie i zmienić kod pocztowy nic się nie dzieje. Wygląda na to, że straciła wiążącą.

Najpierw próbowałem dodając catchOnError przed wywołaniem bindTo metoda ale czytałem tutaj w komentarzu, że nie powinny być traktowane jako część UIBinding: http://blog.scottlogic.com/2014/05/11/reactivecocoa-tableview-binding.html

Domyślam powinien obsługiwać go w metodzie:

func restaurants() -> Observable<[Restaurant]> { 
    return restaurantSearch 
     .observeOn(MainScheduler.instance) 
     .flatMapLatest { postcode -> Observable<[Restaurant]?> in 
      return self.getRestaurants(postcode, cuisine: "", restaurantName: "") 
     }.replaceNilWith([]) 
} 

Więc mam 2 pytania:

1) Gdzie i jak należy sobie radzić w błąd sieciowy?

2) Dlaczego tabela Widok nie aktualizuje się po ponownym uruchomieniu w Internecie?

Każda pomoc bardzo ceniona.

Odpowiedz

8

Osobiście obsługuję błędy sieciowe w usługach, które generują/analizują żądania sieciowe. Dobrym sposobem na to byłoby zawarcie w wynikach Twojej sieci pewnego rodzaju wyliczenia (podobnie jak opcjonalne, ale z błędem, jeśli zero). Więc masz coś takiego:

enum APIResult<T> { 
    case Success(T) 
    case Error(ErrorType) 
} 

I wówczas usługi byłoby Jeśli używasz MVVM architekturę byś następnie filtrować tylko dobre wyniki w świetle modelu i zapewniają, że dane, aby powrócić coś jak to

Observable<APIResult<[Restaurant]>> 

zobacz kontroler.

Należy również spojrzeć na jednostkę Driver. Jest to jednostka tworzona specjalnie dla powiązań UI, więc subskrybuje tylko główny wątek, nigdy błędy i akcje nie dają wyniku.

Aby przetłumaczyć Obserwowalne do sterownika użyć jednej z trzech metod:

func asDriver(onErrorJustReturn onErrorJustReturn: Self.E) -> RxCocoa.Driver<Self.E> 
func asDriver(onErrorDriveWith onErrorDriveWith: RxCocoa.Driver<Self.E>) -> RxCocoa.Driver<Self.E> 
func asDriver(onErrorRecover onErrorRecover: (error: ErrorType) -> RxCocoa.Driver<Self.E>) -> RxCocoa.Driver<Self.E> 

Podejście to automatycznie czynienia z drugim pytaniem, bo gdy Obserwowalne emituje błąd, wszyscy abonenci wypisać, tj. to kończy strumień. Spróbuj umieścić .debug() za swoim połączeniem api.restaurants() i przekonaj się sam, że anuluje subskrypcję.

Możesz przeczytać więcej o Driver i innych jednostkach here

+0

Niezły! Osobiście, gdy używam modeli widoku, mam również ten model zmiennej w widoku, który informuje o błędach, więc kontroler może słuchać go jako niezależnej jednostki. Poza tym 'APIResult' jest świetny, możesz również użyć [Wynik] (https://github.com/antitypical/Result). – sunshinejr

Powiązane problemy