Combining Alamofire and RxSwift

10,508

You can use RxAlamofire as @Gus said in the comment. But if you are using any library that doesn't support Rx extensions by default you may need to do the conversion by hand.

So for the above code snippet, you can create an observable from the callback handler you had implemented

    func getResultsObservable() -> Observable<Result> {
        return Observable.create{ (observer) -> Disposable in
            locationInfo
                //Make a request
                .doRequest( .... )

                //Call back when request finished
                .completionHandler { result in
                    switch result {
                    case .Success(let info): observer.on(Event.Next(info))
                    case .Failure(let error): observer.on(Event.Error(NetworkError()))
                    }
            }       
            return Disposables.create {
               // You can do some cleaning here      
            }
        }
    }

Callback handlers are implementation to observer pattern, so mapping it to a custom Observable is a straight forward operation.

A good practice is to cancel the network request in case of disposing, for example this is a complete disposable Post request:

return Observable<Result>.create { (observer) -> Disposable in
        let requestReference = Alamofire.request("request url",
            method: .post,
            parameters: ["par1" : val1, "par2" : val2])
            .validate()
            .responseJSON { (response) in
                switch response.result{
                case .success:
                     observer.onNext(response.map{...})
                     observer.onCompleted()
                case .failure:
                    observer.onError(NetworkError(message: response.error!.localizedDescription))
                }
        }
        return Disposables.create(with: {
            requestReference.cancel()
        })

Note: before swift 3 Disposables.create() is replaced with NopDisposable.instance

Share:
10,508
Pham Hoan
Author by

Pham Hoan

Updated on July 26, 2022

Comments

  • Pham Hoan
    Pham Hoan almost 2 years

    I have this custom implementation of Alamofire:

    protocol HTTPProtocol: class {
        typealias RequestType
        typealias RespondType
        func doRequest(requestData: RequestType) -> Self
        func completionHandler(block:(Result<RespondType, NSError>) -> Void) -> Self
    }
    
    //example of a request:
    locationInfo
          //Make a request
        .doRequest(HTTPLocationInfo.RequestType(coordinate: $0))
    
          //Call back when request finished
        .completionHandler { result in
            switch result {
                case .Success(let info): self.locationInfoRequestSuccess(info)
                case .Failure(let error): self.locationInfoRequestFailed(error)
            }               
        }
    

    I want to apply MVVM and RxSwift into my project. However, I can't find a proper way to do this.

    What I want to achieve is a ViewModel and a ViewController that can do these things:

    class ViewController {
        func googleMapDelegate(mapMoveToCoordinate: CLLocationCoordinate2D) {
            // Step 1: set new value on `viewModel.newCoordinate` and make a request
        }
    
        func handleViewModelCallBack(resultParam: ...*something*) {
            // Step 3: subscribeOn `viewModel.locationInfoResult` and do things.
        }
    }
    
    class ViewModel {
        //Result if a wrapper object of Alamofire.
        typealias LocationInfoResult = (Result<LocationInfo.Respond, NSError>) -> Void
        let newCoordinate = Variable<CLLocationCoordinate2D>(kInvalidCoordinate)
        let locationInfoResult: Observable<LocationInfoResult>
    
        init() {
            // Step 2: on newCoordinate change, from step 1, request Location Info
            // I could not find a solution at this step
            // how to make a `completionHandler` set its result on `locationInfoResult`
        }
    }
    

    Any help is deeply appreciated. Thank you.