使用驱动程序在警报 RxSwift 中显示错误响应

Show error response in alert RxSwift using Driver

如何获得驱动程序的错误响应,以便我可以在警报中显示它。当我看到 trait driver is can't error out 时,我应该在订阅时使用 subject 或 behaviorRelay 来获取错误响应。其实我喜欢怎么用driver,但是不知道怎么用driver来传递error response

这是我的网络服务

func getMovies(page: Int) -> Observable<[MovieItem]> {
        
        return Observable.create { observer -> Disposable in
            self.service.request(endpoint: .discover(page: page)) { data, response, error in
                if let _ = error {
                    observer.onError(MDBError.unableToComplete)
                    return
                }
                
                guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
                    observer.onError(MDBError.invalidResponse)
                    return
                }
                
                guard let data = data else {
                    observer.onError(MDBError.invalidData)
                    return
                }
                
                if let decode = self.decode(jsonData: MovieResults.self, from: data) {
                    observer.onNext(decode.results)
                }
                observer.onCompleted()
            }
            return Disposables.create()
        }
    }

这是我的视图模型

protocol ViewModelType {
    associatedtype Input
    associatedtype Output
    
    func transform(input: Input) -> Output
}

class PopularViewModel: ViewModelType {
    
    struct Input {
        let viewDidLoad: Driver<Void>
    }
    
    struct Output {
        let loading: Driver<Bool>
        let movies: Driver<[MovieItem]>
    }
    
    private let service: NetworkDataFetcher
    
    init(service: NetworkDataFetcher = NetworkDataFetcher(service: NetworkService())) {
        self.service = service
    }
    
    func transform(input: Input) -> Output {
        let loading = ActivityIndicator()
        let movies = input.viewDidLoad
            .flatMap { _ in
                self.service.getMovies(page: 1)
                    .trackActivity(loading)
                    .asDriver(onErrorJustReturn: [])
            }
        
        let errorResponse = movies

        
        return Output(loading: loading.asDriver(),movies: movies)
    }
}

这就是我在 viewController

中绑定 viewModel 的方式
let input = PopularViewModel.Input(viewDidLoad: rx.viewDidLoad.asDriver())
        
        let output = viewModel.transform(input: input)
        
        output.movies.drive { [weak self] movies in
            guard let self = self else { return }
            self.populars = movies
            self.updateData(on: movies)
        }.disposed(by: disposeBag)
        
        
        
        output.loading
            .drive(UIApplication.shared.rx.isNetworkActivityIndicatorVisible)
            .disposed(by: disposeBag)

您以与处理 ActivityIndi​​cator 相同的方式执行此操作...

The ErrorRouter type below can be found here.

这是一个很常见的模式,I have created an API class 会自动解决这个问题。

class PopularViewModel: ViewModelType {

    struct Input {
        let viewDidLoad: Driver<Void>
    }

    struct Output {
        let loading: Driver<Bool>
        let movies: Driver<[MovieItem]>
        let displayAlertMessage: Driver<String>
    }

    private let service: NetworkDataFetcher

    init(service: NetworkDataFetcher = NetworkDataFetcher(service: NetworkService())) {
        self.service = service
    }

    func transform(input: Input) -> Output {
        let loading = ActivityIndicator()
        let errorRouter = ErrorRouter()

        let movies = input.viewDidLoad
            .flatMap { [service] in
                service.getMovies(page: 1)
                    .trackActivity(loading)
                    .rerouteError(errorRouter)
                    .asDriver(onErrorRecover: { _ in fatalError() })
            }

        let displayAlertMessage = errorRouter.error
            .map { [=10=].localizedDescription }
            .asDriver(onErrorRecover: { _ in fatalError() })

        return Output(
            loading: loading.isActive.asDriver(onErrorRecover: { _ in fatalError() }),
            movies: movies,
            displayAlertMessage: displayAlertMessage
        )
    }
}