27224


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

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

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

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

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

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


CC BY-SA 3.0
2016-06-30T05:29:06.983
27211
2016-06-30T12:29:32.127
2016-06-30T05:40:17.887
16765
16765
question
swift swift2
Alamofireでの処理について


[参考サイト](http://qiita.com/kazuhirox/items/9ecb25bc238ad2d47ff0)

↑ こちらのサイトのやり方で無事処理させることが出来ました。

[code]

    //ロックの取得
    var keepAlive = true
    
    Alamofire.request(.POST, url, headers: headers, encoding: .JSON)
        .responseJSON { response in
            ・・・データを受信した際の処理・・・
            //ロックの解除
            keepAlive = false
    }
    
    //ロックが解除されるまで待つ
    let runLoop = NSRunLoop.currentRunLoop()
    while keepAlive &&
        runLoop.runMode(NSDefaultRunLoopMode, beforeDate: NSDate(timeIntervalSinceNow: 0.1)) {
        // 0.1秒毎の処理なので、処理が止まらない
    }
    
    ・・・後続の処理・・・
    
[/code]


CC BY-SA 3.0
2016-06-30T10:13:44.023
27217
2016-06-30T10:13:44.023
16765
27211
answer


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

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

[code]

        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のレスポンスに対する処理
                        }
                }
        }
    
[/code]

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

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

[code]

    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のレスポンスに対する処理
    }
    
[/code]

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

[code]

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

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

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


CC BY-SA 3.0
2016-06-30T12:29:32.127
27224
2016-06-30T12:29:32.127
13972
27211
answer