如何使用Moya和RxSwift检查互联网?

AMA*_*N77 7 connectivity internet-connection rx-swift moya swift4

据我所知,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()

 }
}
Run Code Online (Sandbox Code Playgroud)

我正在提出以下要求:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,如果我想在每个Moya请求之前检查连接,那么最好的方法是什么?

  1. 为Moyas内部之一写一个扩展名来检查
  2. 使用Moya插件(准备)进行检查
  3. 到目前为止,其他一些花哨的裤子没有用到......

出于可读性原因,我特别希望为每个API调用添加可访问性检查.但我有兴趣听听以前使用过的方法.

感谢您提供的任何帮助.

iWh*_*Buy 2

我特别不想为每个 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>>
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,网络服务具有单一功能,可以接受所有必要的参数。当您将所有请求包装到一个函数中时 - 您可以在该函数中添加您想要的所有内容。甚至可达性检查!

我想在发出每个 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
    }
}
Run Code Online (Sandbox Code Playgroud)

它应该符合,Disposable因为它将被using操作员使用。

那么,如何使用它:

Observable<Bool>
    .using({ ReachabilityInformer() }, observableFactory: { (informer: ReachabilityInformer) -> Observable<Bool> in
        return informer.observableReachable()
    })
Run Code Online (Sandbox Code Playgroud)

请求应该使用 this 开始Observable。如果存在连接,true您应该flatMap发送 Moya 请求。如果是false,那么您应该返回失败或抛出错误。当请求完成时,using操作员将确保ReachabilityInformer释放该资源。

PS 未经测试,只是一些需要考虑的信息