34
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Moya+RxSwift+CodableでAPI通信

Posted at

#はじめに

AlamofireをラップしたMoyaというライブラリを使ってみました。
RxSwift拡張もあるとのことなので、
Moya+RxSwift+Codableということで備忘も兼ねて記事にしました。
Moya:https://github.com/Moya/Moya

#準備

今回はCocoapodsを使いました。

pod 'Moya/RxSwift'

#APIの定義

MoyaではTargetTypeプロトコルに準拠したenumでAPIを定義します。
今回は簡単なログインAPIな想定です。

Login.swift
enum Login {
	// パスごとにcaseを切り分ける
    case login(id: String, pass: String)
}

extension Login: TargetType {
	// ベースのURL
    var baseURL: URL {
        return URL(string: "https://hogehoge.com")!
    }
    
    // パス
    var path: String {
        switch self {
        case .login:
            return "/login"
        }
    }
    
    // HTTPメソッド
    var method: Moya.Method {
        switch self {
        case .login:
            return .post
        }
    }
    
    // スタブデータ
    var sampleData: Data {
        let path = Bundle.main.path(forResource: "login_stub", ofType: "json")!
        return FileHandle(forReadingAtPath: path)!.readDataToEndOfFile()
    }
    
    // リクエストパラメータ等
    var task: Task {
        switch self {
        case .login(let id, let pass):
            return .requestParameters(parameters: ["id" : id, "pass": pass], encoding: URLEncoding.default)
        }
    }
    
    // ヘッダー
    var headers: [String: String]? {
        return nil
    }
}

MoyaではStubとしてローカルのjsonをレスポンスとして返すことが出来ます。
これが特に便利に感じました。

デコード用にDecodableに準拠したstructを定義します。

struct LoginResponse: Decodable {
    let userId: String
}

#カスタム通信クラスを定義

MoyaはAlamofireをラップしているため、タイムアウト等を設定する場合には、
SessionManagerを別途カスタムする必要があります。
そのため、通信クラスであるMoyaProviderを継承したCustomMoyaProviderクラスを定義します。

CustomMoyaProvider.swift
final class CustomMoyaProvider<T: TargetType>: MoyaProvider<T> {
    
    public init(endpointClosure: @escaping EndpointClosure = MoyaProvider.defaultEndpointMapping,
                requestClosure: @escaping RequestClosure = MoyaProvider.defaultRequestMapping,
                stubClosure: @escaping StubClosure = MoyaProvider.neverStub,
                callbackQueue: DispatchQueue? = nil,
                plugins: [PluginType] = [],
                trackInflights: Bool = false) {
        
        let sessionManager: SessionManager = {
            let configuration = URLSessionConfiguration.default
            // タイムアウトを設定する
            configuration.timeoutIntervalForRequest = 30
            return SessionManager(configuration: configuration)
        }()
        
        super.init(endpointClosure: endpointClosure,
                   requestClosure: requestClosure,
                   stubClosure: stubClosure,
                   callbackQueue: callbackQueue,
                   manager: sessionManager,
                   plugins: plugins,
                   trackInflights: trackInflights)
    }
    
}

#API通信呼び出し

MoyaProviderが破棄されてしまうとSubscribeも止まってしまうため、
プロパティとして定義します。
前述したStubを利用する設定をCustomMoyaProvider定義時に渡します。
neverStub...通常のAPI通信
immediatelyStub...Stubを返す
delayedStub(x)...x秒後にStubを返す

private let loginProvider = CustomMoyaProvider<Login>(stubClosure: MoyaProvider.delayedStub(2))
private let disposeBag = DisposeBag()

通信します。
レスポンスをmapでdecodeし、subscribeに流します。

loginProvider.rx
    .request(.login(id: "id", pass: "pass"))
    .map { (response) -> LoginResponse? in
         return try? JSONDecoder().decode(LoginResponse.self, from: response.data)
    }.subscribe(onSuccess: { (response) in
         if let unwrappedResponse = response {
             print(unwrappedResponse)
         } else {
             print("error")
         }
    }, onError: { (error) in
         print("error")
    })
    .disposed(by: disposeBag)

通信部もシンプルでよいです。

以上となります。
何かございましたら指摘してくださると大変喜びます。

34
30
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
34
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?