AwaitkitとAlamofireでAPIにアクセス【swift 4】

iOSアプリ

この前はflaskでAPIサーバーを構築する記事を書きましたが、
今回はiOSアプリから非同期でAPIにアクセスする方法を紹介します。

前回の記事↓

flask-restfulとAuthlibを使ったAPIの作成方法【python】

非同期処理にAwaitkit、httpリクエストにはAlamofireを使用します。
どちらもCocoaPodsでインストール可能です。

サンプルのxcodeプロジェクトはこちら

(※ここではPromiseやasync, awaitについて詳しい説明はしません。
Javascript関係でググれば色々出てきますので、そちらを参照してください。)

非同期処理の連鎖

「特定のタスクの完了を待って、その結果に応じて別のタスクを行いたい」

という状況はよくあります。

例えば、

  1. ユーザ登録をする
  2. ログイン処理を行う
  3. アプリのホーム画面に遷移する

という処理を行いたいとします。

この手順は、それぞれのタスクの完了を待って、順番に行わなければいけません。

なぜなら、ユーザが存在しないのにログインはできないし、
ログインしていなければホーム画面に行くことはできないからです。

引数として渡す

順次の実行を実現するためにまず思いつくのがこんな方法です。

  1. 「ユーザ登録」のメソッドに「ログイン処理」のメソッドを渡しておく
  2. 「ユーザ登録」の最後で受け取ったメソッドを実行する
  3. 「ホーム画面遷移」も同様に処理する

これを実装すると、呼び出し元のコードはこんな感じになります。
(swiftは最後の引数としてclosure(無名関数)を取る場合は外に出して書けます)

この程度の最低限なコードならまだいいですが、
実践ではもっとたくさんのコードとエラー処理が加わってきます。
しかも処理が増えれば増えるほどネストが深くなっていくというのが最悪です。

then

Promisekitを使うと以下のように書けます。

Promiseというのは、JavascriptのPromiseをswiftに移植したものです。
次のawaitも同様です。

1つの処理が終わったら、その結果と共に次のthenが実行されます。
createUserの結果がuserとして次のthenで使われていますね)

この方法だといくら処理を繋げても(=thenが増えても)
ネストが深くなることがありません。

また、例外処理はcatchでまとめて行うことができます。

しかし、どうもJavascriptとは違って、
PromisekitのcatchはPromiseを返さないため、
後ろにthenをつなげられないようです。

そういうわけで、swiftのPromisekitにおいては、
1つのcatchで全ての例外処理を行う必要があり、
どのthenで発生した例外なのかわかりづらいという欠点があります。

(Promiseを返すrecoverというファンクションはあるようなんですが、
Awaitkitを使えばいいやと思ってちゃんと調べてません・・・。
あと最近のPromisekitでは最後のthenとしてdoneを使うようです)

await

thenはかなり優秀なのですが、
Awaitkitの提供するawaitはより簡潔でわかりやすいコードが書けます。
例外処理もよりフレキシブルに行いやすくなっています。
thenのコードよりも長くなっていますが、
1つのタスクごとに例外処理を行っているからです)

こうなってくると普通の同期的なコードと変わりありません。
当然、一行ずつ順次実行されますし、createUserの戻り値も使用できます。

注意点として、awaitはメインスレッドとは別のスレッドで行う必要があるということです
(デッドロックが発生する)
この辺りの詳しいことは、すみません、よくわかりません。

とりあえず、awaitをする場合はasyncで囲えばバックグラウンドで動いてくれるようです。

サンプルプロジェクトの概要

ダミーのjsonデータを返してくれるサービスを使って次のような動作を実現します。

  1. 全ユーザを取得
  2. 最初のユーザのポストを全て取得

Alamofireを使って、Promiseを返すメソッドを定義します。

エンドポイントはenumで定義します。

呼び出しはこんな感じです。

レポジトリのサンプルはjsonToObjectなんていう便利な関数は作っていないのでもっと汚いのですが、
非同期処理についてはこの方が見やすいと思います。

ネストもしていないですし、例外処理が逐一できます。
thenだとやりづらい、「catchしたらreturn」も簡単にできます。

まとめ

Awaitkitはネット上に情報が少なかったのでここで共有しました。

このライブラリを使えば非同期処理の連鎖が見やすく楽に書けるようになります。
iOSアプリを作っている人は興味があれば使ってみてください。