「エキスパートObjective-C プ
 ログラミング」で始める
      Blocks入門
       朔 洋一郎
      (@saku2saku)
Blocksとは?
BlocksとはiOS 4から利用できるようになったC言
語に対する拡張機能です
自動変数(ローカル変数)の値を伴った無名関数


無名関数とは?
 その名のとおり名前を持たない関数
 JavaのEventListenerやjQueryのコールバック関
 数などを使っている人であれば分かり易いかも
無名関数のJQuery例
     $.ajax({
        type: "POST",
        url: "some.php",
        data: "name=John&location=Boston",
        success: function(msg){
          alert( "Data Saved: " + msg );
        }
     });

上記はJQueryでsome.phpに対して、POSTリクエストを
送った際に成功した場合のコールバック定義の例です
Blocksの構文


^<戻り値の型>(<引数のリスト>) {式};
Blocksの構文
返り値や引数リストが無い場合には省略可能です


   ^void (int tmp) {
      NSLog(@"blocks test %d", tmp);
   }
   または
   ^ (int tmp) {
      NSLog(@"blocks test %d", tmp);
   }
Blocksの構文
返り値や引数リストが無い場合には省略可能です


   ^int (void) {
      return 2;
   }
   または
   ^int {
      return 2;
   }
Blocksの構文
返り値や引数リストが無い場合には省略可能です


   ^void (void) {
      NSLog(@”blocks test”);
   }
   または
   ^{
      NSLog(@”blocks test”);
   }
Blocks変数
Blocksは関数ポインタのように変数に代入すること
も可能になります



<戻り値の型>(^<Blocks変数名>)(<引数リスト>);
Blocks変数
int型の変数を返し、int型の引数を一個取るBlocks
変数blkを定義する場合


int (^blk) (int) = ^int (int count) { return count +2; };

// 呼び出し方
blk(3);
Blocks変数
 typedefを使ってBlocks変数の型を定義することも
 可能です



typedef <戻り値の型>(^<Blocks変数名>)(<引数リスト>);
Blocks変数
typedefを使った例


typedef void (^completeBlock_t)(NSData *data);
completeBlock_t block_ = ^(NSData *data) {
                              //hogehoge;
                         };
Blocksって使えるの?
これだけではわかりにくいですが使えます!
どういう面で使えるのかよくわからないけど?
 処理が分散しない
  デリゲートもいいけど、別メソッドで実装する
  必要があるため、処理の記述場所が分散する
  GCDのコードを書く際に必要
   Grand Central Dispatch(GCD)というマルチ
   スレッド処理の仕組みを使う際に使用
オマケ:GCDって?
GCDはマルチスレッドプログラミングを抽象的に実
装するための仕組み
今回は特に触れませんが、本サンプルの参考書籍
「エキスパートObjective-Cプログラミング」に詳
しく説明されています
 例えば、画像の非同期通信での描画などに役立ち
 ます
サンプルコード

http://workshop.iphonework.biz/files/2012/05/
             BlocksSample.zip
TIPS
TIPS
自動変数のキャプチャ
自動変数の代入
自動変数の参照型の扱い
自動変数のキャプチャ
int型のプリミティブ型はBlocksが定義された時点の
値としてコピーされる
   int main()
   {
     int val = 10;
     const char *fmt = "val = %dn";
     void (^blk)(void) = ^ { printf(fmt, val) };

       val= 2;
       fmt = "These valudes were changed. val = %dn";

       blk();

       return 0;
   }



                   結果は val = 2と表示される
自動変数への代入
自動変数のキャプチャは先程のとおり、Blocks構文
が出現した段階でとられます
そこにBlocks内で値を上書きすることは基本的には
できません(以下はエラーになる)

   int main()
   {
     int val = 20;
     void (^blk)(void) = ^ { val = 2};

       blk();
       printf("val = %dn", val);

       return 0;
   }
自動変数への代入
それでも値の変更をしたい場合には
「__block」指定子を使う必要があります
 _は2つ重ねています
 以下の場合はOK

   int main()
   {
     __block int val = 20;
     void (^blk)(void) = ^ { val = 2};

       blk();
       printf("val = %dn", val);

       return 0;
   }
自動変数の参照型の扱い
参照型はプリミティブ型(int, float, etc)でないク
ラスを持つような型を指します(NSObject, etc)
参照型の場合には変数にはそのポインタが入ります
が、これに足してもBlocksの中で代入はできません
    int main()
    {
      NSMutableArray *array = [[NSMutableArray alloc] init];
      void (^blk)(void) = ^ {
         array = [[NSMutableArray alloc] init];
      };

        blk();

        return 0;
    }
自動変数の参照型の扱い
参照型の場合は代入はできませんが、その変数の持
つメソッドを呼んで、内部状態が変更になるのはOK
です

   int main()
   {
     NSMutableArray *array = [[NSMutableArray alloc] init];
     void (^blk)(void) = ^ {
        NSObject *obj = [[NSObject alloc] init];
        array = [array addObject: obj];
     };

       blk();

       return 0;
   }
ご清聴
ありがとうございました

20120422i phonedeveloperworkshoppublished