Moyaでお手軽API通信
ブログ始めてみたんですけど、特に抱負も何もないので、しれっとMoyaで遊んだ事について書きます。
Moyaって?
APIとか叩く時に作られがちな、"APIManager"とか"NetworkModel"みたいな、 ネットワークを抽象化するレイヤーの役割をしてくれるライブラリ。 内部的にはAlamofireを叩いていて、言うならAlamofireのラッパーとも言えるかもしれない(言えないかもしれない)。
何が便利?
公式が言うには
個人的に思ったのは
- siestaとかよりhttp通信の層をよく隠してくれるので楽
- 仕組みが割とわかりやすいので使う上でリーズナブル
といったところでしょうか。
使い方
導入
Podfileに
pod 'Moya'
を記入し、pod install
で簡単にインストールできます。
なお、Moyaを入れるとAlamofireも一緒に入るので別途記述する必要はありません。
ちなみにSwift Package ManagerやCarthageでも導入可能です。
今回は、 github.com を使って基本的な使い方をなぞってみます。 MoyaのレポジトリにあるBasicUsageとほぼ同じ内容です。
enumを作成
Moyaでは、自分が使いたいAPIの情報をenumに持たせます。 まずは、それぞれのAPIターゲットをenumとして列挙します。 また、それぞれのターゲットに対し渡すパラメータがある場合は、連想値でこれを定義します。
import Moya enum HackersNewsAPI { case item(id: Int) case user(id: String) case maxItem case topStories case newStories }
また、このenumはTargetType
プロトコルに準拠する必要があります。
具体的には
- var baseURL: URL
- var path: String
- var method: Moya.Method
- var parameters: [String: Any]
- var parameterEncoding: ParameterEncoding
- var sampleData: Data
- var task: Task
のプロパティを設定しなければなりません。 今回は以下のように準拠させます。
extension HackersNewsAPI: TargetType { // ベースURL var baseURL: URL { return URL(string: "https://hacker-news.firebaseio.com/v0")! } // それぞれのターゲットごとのpath var path: String { switch self { case .item(let id), .user(let id): return "/\(id).json" case .maxItem: return "/maxitem.json" case .newStories: return "/newstories.json" case .topStories: return "/topstories.json" } } // それぞれのターゲットごとのhttpメソッド // 今回はgetしかないが、postなどある場合はswitch selfなどで適切な値を返す var method: Moya.Method { switch self { case .item, .user, .maxItem, .newStories, .topStories: return .get } } // 今回はパラメーターとして渡さないのですべてnil var parameters: [String: Any]? { return nil } // パラメーターのエンコーディング指定 // リクエストボデイにjsonとしてセットすることもできる var parameterEncoding: ParameterEncoding { return URLEncoding.default } // テスト時に使われる(なんでマストなのかわからない) // めんどくさかったので今回はずるします var sampleData: Data { return Data() } var task: Task { switch self { case .item, .user, .maxItem, .newStories, .topStories: return .request } } }
以上でenumの準備は完了です。
ここまで書いて、題材にしたAPIがあんま良くなかったことに気づく。 が、面倒くさいので強行します。
MoyaProviderを使ってAPIリクエストする
enumの準備が整ったら、MoyaProviderを生成し、リクエストを送ることができます。
let provider = MoyaProvider<HackersNewsAPI>() provider.request(.newStories) { result in }
provider.requestの第二引数となっているクロージャが受け取っているresultは、
.success(Moya.Response)
と.failure(MoyaError)
を持つenumです。
なので基本的には
provider.request(.newStories) { result in switch result { case let .success(moyaResponse): do { try moyaResponse.filterSuccessfulStatusCodes() let data = try moyaResponse.mapJSON() // do something with the data } catch { // failed to convert to JSON } case let .failure(error): // failed at api access } }
のようにしてエラー検知すると良いと思います。
filterSuccessfulStatusCodes
は、ステータスが200~299でなければ例外を投げるメソッド。
mapJSON
は名前の通りデータをJSONにマッピングしてくれるメソッドです。
どちらもMoya.Responseに組み込まれたメソッドです。
まとめ
今回は本当に触りしかやりませんでしたが、Moyaは、APIリクエストの際に挟み込めるクロージャーや、 テストを意識した機能、RX対応など、まだまだ魅力的な機能を持っています。 特にRX対応は割とAPIもイケてると思うので是非触ってみてもらえたらなと思います。
一応今回のソース