Как проверить наличие интернета с помощью Moya и RxSwift?

Насколько я понимаю, Alamofire встроен со встроенной функцией Reachability, поэтому мой собственный обработчик будет выглядеть примерно так:

import Alamofire

let reachabilityManager = NetworkReachabilityManager()
reachabilityManager.listener = { status in

switch status {

case .notReachable:
 print("The network is not reachable")
 self.onInternetDisconnection()

case .unknown :
 print("It is unknown whether the network is reachable")
 self.onInternetDisconnection() // not sure what to do for this case

case .reachable(.ethernetOrWiFi):
 print("The network is reachable over the WiFi connection")
 self.onInternetConnection()

case .reachable(.wwan):
 print("The network is reachable over the WWAN connection")
 self.onInternetConnection()

 }
}

Я делаю запрос через:

let provider = MoyaProvider<MyMoyaRequest>()
let token = provider.request(.start(
    username:self.email.value, 
    password: self.password.value) { result in

    switch result { 
    case let .success(moyaResponse):
        //handle success
    case let .failure(error):
        //handle failure
    }
}

Итак, если я хочу, чтобы перед каждым запросом Moya проверялось подключение, как лучше всего это сделать?

  1. Напишите расширение для одного из внутренних устройств Moyas, чтобы сначала проверить
  2. Используйте плагин Moya (подготовьте), чтобы проверить
  3. Какие-то модные штаны, о которых пока и не догадывались ...

Я специально не хочу добавлять проверку достижимости к каждому вызову API из соображений удобочитаемости. Но мне интересно услышать об использованных ранее методах.

Спасибо за любую помощь, которую вы можете предложить.


person AMAN77    schedule 25.10.2017    source источник


Ответы (1)


Я специально не хочу добавлять проверку достижимости к каждому вызову API.

Возможно, разумным решением будет обернуть все вызовы API в какую-нибудь службу. Например, как я сделал это в своем последнем приложении:

public protocol NetworkServiceType: class {
    /// Cancellable request
    func observableRequest<T,C>(api: AnyApi<T>, cancel: Observable<C>, headers: [AUApi.Header: String], indicator: ActivityRelay?, logs: NetworkServiceLogs, timeout: TimeInterval, queue: DispatchQueue) -> Observable<Output<T>>
}

Как видите, сетевой сервис имеет единственную функцию, которая может принимать все необходимые параметры. А когда вы объедините все свои запросы в одну функцию - вы можете добавить в эту функцию все, что захотите. Даже проверка доступности!

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

Есть несколько способов сделать это:

  1. Я бы создал общую службу реактивной достижимости и внедрил ее в сетевую службу. Итак, перед каждым запросом Moya вы можете позвонить withLatestFrom и узнать последний статус в вашей службе доступности.
  2. Вы можете создать службу доступности для каждого запроса и удалить ее после завершения запроса.

Я с удовольствием покажу вам, как создать второй вариант. Первое, что нам нужно, это немного ReachabilityInformer:

final class ReachabilityInformer: Disposable {

    private lazy var networkReachabilityManager: NetworkReachabilityManager? = NetworkReachabilityManager(host: "www.google.com")
    private lazy var relayNetworkReachable = PublishRelay<Bool>()

    init() {
        switch networkReachabilityManager {
        case .none:
            relayNetworkReachable.accept(false)
        case .some(let manager):
            manager.listener = { [weak informer = self] status in
                switch status {
                case .notReachable:
                    informer?.relayNetworkReachable.accept(false)
                case .unknown:
                    break
                case .reachable:
                    informer?.relayNetworkReachable.accept(true)
                }
            }
        }
        networkReachabilityManager?.startListening()
    }

    func observableReachable() -> Observable<Bool> {
        return relayNetworkReachable
            .asObservable()
            .distinctUntilChanged()
    }

    func dispose() {
        networkReachabilityManager?.stopListening()
        networkReachabilityManager?.listener = nil
        networkReachabilityManager = nil
    }
}

Он должен соответствовать Disposable, потому что он будет использоваться оператором using.

Итак, как пользоваться:

Observable<Bool>
    .using({ ReachabilityInformer() }, observableFactory: { (informer: ReachabilityInformer) -> Observable<Bool> in
        return informer.observableReachable()
    })

Запрос должен быть запущен с использованием этого Observable. Если соединения существуют true, вы должны flatMap отправить свой запрос Moya. Если это false, вы должны вернуть ошибку или выдать ошибку. Когда запрос будет завершен, оператор using убедится, что ReachabilityInformer освобожден.

P.S. Не проверено, просто некоторая информация для размышления

person iWheelBuy    schedule 05.07.2018
comment
Привет @iWheelBuy, я немного запутался в приведенном выше коде, не могли бы вы объяснить - person Paresh. P; 29.08.2019
comment
@MeSolutionanalysts Извините, у меня нет времени, чтобы дать вам подробный ответ. - person iWheelBuy; 29.08.2019
comment
Я добавил звонки startListening() и stopListening(), иначе не работает - person Vadim Popov; 03.10.2019