Imagine I have a networking client, using RxSwift
to wrap URLSession
.
I'd like to use a guard
statement and return an error, however I am getting an error that
Non-void function should return a value
Which makes sense, however I am unsure how to handle this with RxSwift
.
class NetworkClient {
var task: URLSessionDataTask = URLSessionDataTask()
var session: SessionProtocol = URLSession.shared
var request: URLRequest?
func call<T: Codable>(_ request: URLRequest) -> Single<T> {
return Single<T>.create(subscribe: { [weak self] observer -> Disposable in
guard let `self` = self else { observer(.error(NSError(domain: "", code: 0, userInfo: [:]))); return }
self.task = self.session.dataTask(with: request, completionHandler: { data, response, error in
})
return Disposables.create {
self.task.cancel()
}
})
}
}
Just use:
guard let `self` = self else { observer(.error(NSError(domain: "", code: 0, userInfo: [:]))); return Disposables.create() }
However, I have to say I'm not a fan of the class at all. First, RxSwift already has a wrapper around dataTask:
func response(request: URLRequest) -> Observable<(response: HTTPURLResponse, data: Data)>
which can be called by:
URLSession.shared.rx.response(request: myRequest)
There's also data(request:)
which will check the statusCode and emit an error if it's not in the 200's.
You can simply inject the function instead of adding the complexity of wrapping it in an object that provides no value add. For example:
struct MyViewModel {
init(serverResponse: @escaping (URLRequest) -> Observable<Data>)...
}
Which can be called by:
let myViewModel = MyViewModel(serverResponse: URLSession.shared.rx.data)
In testing, you can simply pass a closure that returns Observable<Data>.just(myTestData)
.