post Image
RxSwiftとAlamofireとObject Mapperで

この記事では
HTTPのレスポンスとしてJSONを返却するサーバにリクエスト、
結果をObject Mapperでマッピングするまでの処理を、
RxSwiftで書いてみる

動作確認用のエンドポイントとしてhttpbinを使う
https://httpbin.org/ip

response.json
{
  "origin": "127.0.0.1"
}

まずObjectMapperのマッピングクラスを用意する

HttpbinIp.swift
import ObjectMapper

class HttpbinIp: Mappable {

    var origin: String?

    required init?(map: Map){
    }

    func mapping(map: Map) {
        origin<-map["origin"]
    }
}

リクエストするURLを解決する
URLComponentsエクステンション

HttpClient+UrlComponents.swift
extension URLComponents {

    static func httpbin(_ path_:String) -> URLComponents {
        var res = URLComponents()
        res.scheme = "https"
        res.host = "httpbin.org"
        res.path = path_
        return res
    }

    static func httpbin(_ path_:String, query_:[URLQueryItem] ) -> URLComponents {
        var res = URLComponents()
        res.scheme = "http"
        res.host = "httpbin.org"
        res.path = path_
        res.queryItems = query_
        return res
    }

}

HTTPリクエストし結果をHttpbinIpオブジェクトへマッピングする
HTTPクライアント

HTTPClient.swift
import UIKit
import Alamofire
import RxSwift
import RxCocoa
import ObjectMapper


extension URLComponents {

    static func httpbin(_ path_:String) -> URLComponents {
        var res = URLComponents()
        res.scheme = "https"
        res.host = "httpbin.org"
        res.path = path_
        return res
    }

    static func httpbin(_ path_:String, query_:[URLQueryItem] ) -> URLComponents {
        var res = URLComponents()
        res.scheme = "http"
        res.host = "httpbin.org"
        res.path = path_
        res.queryItems = query_
        return res
    }

}

class HTTPClient{

    func request(
        method: Alamofire.HTTPMethod,
        path: String,
        parameters: [String: Any]? = nil
        ) -> Observable<DataResponse<Any>> {
        return Observable.create { observer in
            let req = self.request_base(
                method: method,
                urlComponents: URLComponents.httpbin(path),
                parameters: parameters)
                .responseJSON { response in
                    observer.onNext(response)
                    observer.onCompleted()
            }

            return Disposables.create(with:){
                req.cancel()
            }
        }
    }

    func map<T: Mappable>(response:DataResponse<Any>
        ) -> Observable<T> {
        return Observable.create { observer in
            if let m: T = Mapper<T>().map(JSONObject: response.value){
                observer.onNext(m)
                observer.onCompleted()
            }
            observer.onError(HttpClientError.jsonSerializationFailed.error)
            return Disposables.create(with:){

            }
        }
    }
}

以下のようにObservableオブジェクトとし呼び出す

SomeViewController.swift
    func getIp() -> Observable<DataResponse<Any>>{
        return HTTPClient().request(
            method: .get,
            path: "/ip"
        )
    }

    func someMethod(){
        getIp()
            .flatMap({ it in
                self.map(response: it)
            })
            .subscribe( onNext: { it in
                print(it)
            },onError:{ err in
                print("err",err)
            }).addDisposableTo(disposeBag)
    }

エラーハンドリング

エラー時の処理を書いてみる
以下のstatus code 500を返すエンドポイントにリクエストした時、Observable.errorを発報する。
https://httpbin.org/status/500

エラーオブジェクト

HttpClientError.swift
public enum HttpError: Error {
    case responseSerializationFailed    
    case statusCodeValidationFailed     
    case dataSerializationFailed       
    case jsonSerializationFailed
}

呼び出し例

SomeViewController.swift
    func status500() -> Observable<DataResponse<Any>>{
        return HTTPClient().request(
            method: .get,
            path: "/status/500"
        )
    }

    func someFunction(){
        let status = status500()
            .flatMap { it -> Observable<DataResponse<Any>> in
            if(it.response?.statusCode == 500){
                return Observable.error(HttpError.statusCodeValidationFailed)
            }
            return Observable.just(it)
        }
        status.subscribe(onNext: { (it) in
            print(it)
        }, onError: { (err) in
            if let error = err as? HttpError{
                switch error {
                case .statusCodeValidationFailed:
                    print("status code validation failed \(error)")
                default:
                    print("other HttpClientError error \(error)")
                }
            }else{
                print("unknown error \(err)")
            }
        }).addDisposableTo(disposeBag)

    }



TBD

RxSwiftの便利な機能

distinctUntilChange

combineLatest

timeout

retry

find


『 Swift 』Article List
Category List

Eye Catch Image
Read More

Androidに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

AWSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Bitcoinに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

CentOSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

dockerに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

GitHubに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Goに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Javaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

JavaScriptに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Laravelに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Pythonに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Rubyに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Scalaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Swiftに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Unityに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Vue.jsに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Wordpressに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

機械学習に関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。