ニューラル株式会社|ハイブリッドOS|File System|ARM|Android|Java|制御システム|オープンシステム

 

技術者コラム

 
フォーム
 
第9回目:iOSの非同期API(Part4)
2014-04-06
筆者:村田
 
こんにちは。
 
前回、ブロック構文を用いたプロトコルデリゲートの置き換えを紹介したのですが、使いどころと注意点についてコメントしたいと思います。
 
[使いどころ]
①例としてあげたHTTP通信開始→終了イベント通知のように非同期処理の開始とイベント通知にシーケンシャルな関連性が強い場合には、処理を近くに書けるので可読性向上のメリットがあります。
 
// 処理開始
AsyncMethodStart: request
didEventA:^() {
  // 何かイベント処理
}
didEventB:^() {
  // 何かイベント処理
}
 
②ブロック構文はクロージャなので、呼び出し側の自動変数を非同期処理側に簡単に渡せます。プロトコルデリゲートの場合、インスタンス変数を経由しなければならないので少々面倒です。
 
[注意点]
 
①View(画面)のイベントハンドラはシーケンシャルな関連がないので、わざわざブロックで書けるようにする必要は無いと思います。素直にプロトコルを実装した方がいいでしょう。
 
②ブロックの中でブロックを書くような以下の書き方は、JavaScriptなどで良く見られますが、インデントが深くなりメソッドも大きくなるのであまりオススメできません。
 
AsyncMethodA: request
didEventA:^() {
  AsyncMethodB: request
  didEventB:^() {
  }
}
 
最後に突然横道に逸れますが、C#の構文を一つ紹介したいと思います。まず注意点②の極端な例を見てみましょう。(以下はObjC風疑似コード)
 
-(void) hoge
{
  AsyncConnectMethod:                   // 非同期接続を開始して、
  didConnectEvent:^() {                   // 接続完了したら、
    AsyncReceiveMethod                   // まずは受信を開始して、
    didReceiveEvent:^() {                  // 受信できたら、
      AsyncSendMethod:                    // 応答を送信して、
      didSendCompleteEvent:^() {     // 送信完了したら・・・
      }
    }    
  }
}
 
上記のようにブロックの中で次の非同期処理を連鎖をさせる場合、インデントが深くなり読みづらいコードになります。C#では非同期メソッドの待ち合わせを行うawaitという演算子があり、以下のように書けます。
 
async void hoge()
{
  await AsyncConnectMethod();
  await AsyncReceiveMethod();
  await AsyncSendMethod();
}
 
AsyncConnectMethodを呼び出した後、非同期処理が完了するまで一度hogeを抜けて別の処理を実行でき、非同期処理が終わるとhogeの続きのAsyncReceiveMethodから処理を復帰継続します。シーケンシャルなクロージャ連鎖には持ってこいの記法です。
 
別の言語ではクロージャの連鎖を「継続」って呼んだり、「コルーチン」をクロージャ連鎖で実現していたりと、クロージャ関連は面白いネタになりそうです。きちんと勉強したら記事にまとめたいと思います^^
 
以上