Cocoa勉強会#43-Blocksを使う

494 views

Published on

Cocoa勉強会#43
2010/11/27
Blocksを使う
新居雅行

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Cocoa勉強会#43-Blocksを使う

  1. 1. Blocksを使う Masayuki Nii - nii@msyk Cocoa Study #43 Nov 27, 2010 2010年11月26日金曜日
  2. 2. Agenda Blocksとは いろいろな場合の書き方 マクロと型定義でより見やすく 2010年11月26日金曜日
  3. 3. Blocks iOS 4/Snow Leopardよりサポート プログラム自体をデータとして扱う プログラム自体を変数に代入 定義した場所と別の場所で実行 • • 他の言語では「クロージャ」 iOS/Mac OS Xではこの言い方はしていない • 2010年11月26日金曜日
  4. 4. もっともシンプルな例 ! void (^proc1)(void) = ^(void){ NSLog( @"==proc1=="); }; ! proc1; ! proc1(); proc1は変数、よって「void (^)(void)」は型 ^がともかく「関数」ないしは「その始まり」 戻り値は^の左(この場合はvoid) 引数は^の右(この場合はなし) • • • proc1だけではエラーは出ないが実行もされない 参照するだけで呼び出されない • proc1()によって、{ ... }の部分を実行する 2010年11月26日金曜日
  5. 5. 引数があるBlocksの例 ! int (^proc2)(id, int) = ^(id str, int c){ ! ! for( int i=0 ; i < c; i++ )! { ! ! ! NSLog( @"%@",str ); ! ! } ! ! return 99; ! }; //! proc2(); --> error: too few arguments to block 'proc2' ! int x = proc2( @"Song", 3 ); ! NSLog( @"x=%d", x ); //! xの値は99 変数はproc2、型的なものは int(^)(id, int) =より後は本体、最初に仮引数を定義 本体の定義には引数は不要 • • 2010年11月26日金曜日
  6. 6. Block内外での変数と変更可能性 ! ! ! ! __block int b = 100; int c = 200; void (^proc3)(void) = ^(void){ b=b+c; }; proc3();! NSLog( @"b=%d", b );! // bの値は300 ! proc3();! NSLog( @"b=%d", b );! // bの値は500 //! void (^proc3)(void) = ^(void){ b++; c++; }; --> error: increment of read-only variable 'c' __block宣言した変数はBlocks内で書き込める そうじゃないものは書き込みができない • 2010年11月26日金曜日
  7. 7. 引数にBlocksをもつ関数を定義する void function1( int a, void (^b)(id,int))! { ! b(@"pack",a); } : ! function1( 3, ^(id x,int y) { NSLog(@"%@,%d",x,y); } ); ! ! void(^f1)(id,int) = ^(id x, int y){ NSLog(@"%@,%d",x,y); }; ! function1( 3, f1 ); スケルトン Blocksの引数の返り値はvoid 引数は「変数定義」と同じ形式 • • 関数の利用時 最初に紹介した基本型の右側と同じ • 2010年11月26日金曜日
  8. 8. 引数にBlocksを持つ関数(戻り値あり) int function2( int a, int (^b)(id,int))!{ ! int i=b(@"pack",a); ! return i; エラーに } : なる場合 function2( 3, ^(id x,int y) { return 4; } ); ! function2( 3, ^(id x,int y) { } ); //-->error: incompatible block pointer types initializing 'void (^)(struct objc_object *, int)', expected 'int (^)(struct objc_object *, int)' function2( 3, int ^(id x,int y) { return 4; } ); //-->expected expression before 'int' function2( 3, (int)^(id x,int y) { return 4; } ); //-->invalid conversion initializing integer 'int', expected block pointer function2( 3, int(^)(id x,int y) { return 4; } ); //-->expected expression before 'int' function2( 3, (int)(^)(id x,int y) { return 4; } ); //-->expected specifier-qualifier-list before ')' token 2010年11月26日金曜日
  9. 9. 関数定義と長過ぎる引数 void samplefunc( int, void (^)(NSString*, NSString*, NSArray*, NSMutableArray*, NSMutableDictionary*, int, int)); void samplefunc( int x, void (^func)(NSString* z1, NSString* z2, NSArray* z3, NSMutableArray* z4, NSMutableDictionary* z5, int s1, int s2)) { func(....);[z1 release]; } : samplefunc( 3, ^(NSString* z1, NSString* z2, NSArray* z3, NSMutableArray* z4, NSMutableDictionary* z5, int s1, int s2){ [z1 release]; }); 分け分からん… 2010年11月26日金曜日
  10. 10. マクロ定義で見やすくする #define LONGPARAM (NSString* z1, NSString* z2, NSArray* z3, ! NSMutableArray* z4, NSMutableDictionary* z5, int s1, int s2) void samplefunc2( int, void (^)LONGPARAM); void samplefunc2( int x, void (^func)LONGPARAM) {} : samplefunc2( 3, ^LONGPARAM{ ! NSLog( @"%@",z2 ); }); 引数の並びを仮引数込みでマクロ定義する それを利用して、スケルトン、インプリメンテー ション、利用時、それぞれで利用する スケルトンでは仮引数は無視されるので、指定して あっても問題ない • • 2010年11月26日金曜日
  11. 11. Blocksの型定義 #define PARAM (id x,int y) typedef void (^func1param)PARAM; typedef int (^func2param)PARAM; : func2param f2p; f2p = ^PARAM{ ! NSLog(@"%@,%d",x,y); ! return 6; }; function2( 3, f2p ); 引数並び、Blocksの型を定義してしまう 引数並びをマクロで定義 戻り値を加えて型の定義 • • プログラム本体はちょっと整理した雰囲気になる 2010年11月26日金曜日
  12. 12. クラス定義でBlocks #define BLOCKPARAM (id x, int y, NSString *s) typedef float(^MyBlock)BLOCKPARAM; @interface TestClass : NSObject { ! MyBlock f; } - (void) myMethod: (MyBlock)bf; @end @implementation TestClass - (void) myMethod: (MyBlock)bf! {! } @end 引数並びのマクロ定義と型の定義を行えば、クラスの 定義もすっきり 2010年11月26日金曜日
  13. 13. マルチタスク NSThreadでマルチタスク 引数で渡したBlocksの実行がなんかおかしい とりあえずはあきらめたが… • • NSInvocationOperation/NSBlockOperationがある NSOperationの派生クラスなので、単純に言えば NSThreadの「今風」な使い方が可能 Blocksで渡したプログラムを、別スレッドで実行で きた • • 2010年11月26日金曜日
  14. 14. 考察 APIにBlocksを使うものが出てきている iOSのバックグランドタスクはこれしかない 避けて通れない • • JavaScriptほどの柔軟性はない 文字列変数からBlocks生成はできない • 文法がなんか腑に落ちるような落ちないような パターンで学習するしかないかな∼ • 2010年11月26日金曜日

×