あまり褒めらた方法ではないのですが、処理を簡単にするためAFNetworkingでの通信を同期で行いたいことはありますよね。
AFNetworkingのNSOperationQueue
にwaitUntilAllOperationsAreFinished
を呼んでやればできるのかとおもいきや、どうも意味が違うらしい。
そこで簡単に思いつくGCDのSemaphoreを使ってコールバックが終わるまで待つようにしてみたところ...
client.get
のところで実行がデッドロックしているようでコールバックブロックが呼ばれません。
APIのログを確認するとサーバにアクセスは来ています。
これ、結構ハマってしまい諦めて別の方法で実装しようかなと思ってたのですが「Are AFNetworking success/failure blocks invoked on the main thread?」を発見してcompletionQueue
の存在を知ります。
たぶんここでcompletionQueue
が設定されていない場合、dispatch_get_main_queue()
が使われるのでデッドロックするのだと思われます。
dispatch_get_global_queue
とかdispatch_queue_create
とかしたものをセットすれば良さそうです。
先ほどのRubyMotionのafmotionを介して実行したサンプルですとAFMotion::Client.build
のDSLブロックに
: response_serializer :json completion_queue Dispatch::Queue.concurrent end
とかできれば良かったのですが、ClientDSLクラスには定義されてないようです。(プルリクチャンスかw) ただ返されるclient
はAFHTTPRequestOperationManagerそのもののようなので使う前に設定してみます。
client.completionQueue = Dispatch::Queue.concurrent
EXC_BAD_ACCESS
ります。RubyMotionのDispatch::Queueオブジェクトは元のGCDオブジェクトそのものではないので当然か。Dispatch::Queue.concurrent.methods
でメソッドを見てみるとdispatch_object
なんてものがありますので、おそらくコレですね。
期待通りに動くようになりました( ˘ω˘)
コメントする