As far as I understand Alamofire is pulled in with built in Reachability, so my own handler would look something like:
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()
}
}
I'm making a request with:
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
}
}
So if I want to have connectivity checked before every Moya Request is made what is the best way to go about it?
I specifically do not want to add a reachability check to every single API call, for readability reasons. But I am interested in hearing about methods previously used.
Thank-you for any assistance you can offer.
I specifically do not want to add a reachability check to every single API call
It might be a reasonable decision to wrap all you API calls into some service. For example how I did it in my last app:
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>>
}
As you can see the network service has a single function that is able accept all the necessary parameters. And when you wrap all your requests into a single function - you can add everything you want inside this function. Even reachability check!
I want to have connectivity checked before every Moya Request is made
There are some ways to do it:
withLatestFrom
and get the latest status from your reachability service.I'd love show you how to create the 2nd variant. The first thing we need is some 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
}
}
It should conform to Disposable
because it will be used by using
operator.
So, how to use it:
Observable<Bool>
.using({ ReachabilityInformer() }, observableFactory: { (informer: ReachabilityInformer) -> Observable<Bool> in
return informer.observableReachable()
})
The request should be started using this Observable
. If connections exists true
you should flatMap
to your Moya Request. If it is false
, then you should return a failure or throw an error. When request is completed, using
operator will make sure that the ReachabilityInformer
is deallocated.
P.S. Not tested, just some information to think about
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With