Alamofireでの処理について

投稿者: Anonymous

Alamofire自体が非同期通信というのは存じております。
Alamofireを利用してデータをPOSTしたいと考えているのですが、
「A」「B」「C」という3つの処理があり、

①「A」が正常に終わると「B」に移行する
②「B」を正常に処理し終えると「C」に移行する。
③「B」で受け取ったデータを元にデータを処理し、「C」の処理で送信し処理を終える。

要するに「A」が終わってから「B」
「B」が終わってから「C」の順番で処理を行うことは可能でしょうか。

「A」「B」「C」それぞれがAlamofireでの処理になります。

例)「A」-> アカウント登録
  「B」-> ログイン要求
  「C」-> ログイン処理のためのハッシュ送信

一つずつキューを使って処理すべきなのでしょうか。

解決

非同期処理をうまく使いこなすコツは「待たない」こと、完了後のデータが必要な処理は完了ハンドラの中に書くことの2点です。

ただ、コメントに示したように「普通に入れ子にする」と、どうひいき目に見ても見やすいとは思えないコードになってしまいます。

    Alamofire.request(.POST, urlA, headers: headersA, encoding: .JSON)
        .responseJSON { response in
            //...Aのレスポンスに対する処理
            let urlB = ...
            let headersB: [String: String] = ...
            Alamofire.request(.POST, urlB, headers: headersB, encoding: .JSON)
                .responseJSON { response in
                    //...Bのレスポンスに対する処理
                    let urlC = ...
                    let headersC: [String: String] = ...
                    Alamofire.request(.POST, urlC, headers: headersC, encoding: .JSON)
                        .responseJSON { response in
                            //...Cのレスポンスに対する処理
                    }
            }
    }

こういう場合、完了ハンドラをクロージャーとして直接書かずに、メソッドで指定すれば少し見やすくなるのではないかと思います。

完了ハンドラ群をこんな感じでメソッドで定義しておきます。

private func onResponseA(response: Response<AnyObject, NSError>) {
    //...Aのレスポンスに対する処理
    let urlB = ...
    let headersB: [String: String] = ...
    Alamofire.request(.POST, urlB, headers: headersB, encoding: .JSON)
        .responseJSON(completionHandler: onResponseB)
}
private func onResponseB(response: Response<AnyObject, NSError>) {
    //...Bのレスポンスに対する処理
    let urlC = ...
    let headersC: [String: String] = ...
    Alamofire.request(.POST, urlC, headers: headersC, encoding: .JSON)
        .responseJSON(completionHandler: onResponseC)
}
private func onResponseC(response: Response<AnyObject, NSError>) {
    //...Cのレスポンスに対する処理
}

後は、最初の完了ハンドラを指定して、最初のリクエストを投げるだけです。

    Alamofire.request(.POST, urlA, headers: headersA, encoding: .JSON)
        .responseJSON(completionHandler: onResponseA)

入れ子にするパターンも、完了ハンドラを別メソッドにするパターンも、要は「前の処理の完了ハンドラの中で、次のリクエストを送信する」ということを続けているだけです。

上のどちらかのやり方で確実に処理ができるはずです。Appleのサンプルコードを見回しても、非同期処理の終了を待ち合わせるためにNSRunLoopを使うようなコードは全くありません。是非ともそんな「脆い」方法をとらず、確実に動作する方法をとられるよう強くお勧めしておきます。

回答者: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *