14

Click here to load reader

Cocoa勉強会#43-Blocksを使う

Embed Size (px)

DESCRIPTION

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

Citation preview

Page 1: Cocoa勉強会#43-Blocksを使う

Blocksを使う

Masayuki Nii - nii@msykCocoa Study #43Nov 27, 2010

2010年11月26日金曜日

Page 2: Cocoa勉強会#43-Blocksを使う

Agenda

Blocksとは

いろいろな場合の書き方

マクロと型定義でより見やすく

2010年11月26日金曜日

Page 3: Cocoa勉強会#43-Blocksを使う

Blocks

iOS 4/Snow Leopardよりサポート

プログラム自体をデータとして扱う•プログラム自体を変数に代入•定義した場所と別の場所で実行他の言語では「クロージャ」• iOS/Mac OS Xではこの言い方はしていない

2010年11月26日金曜日

Page 4: Cocoa勉強会#43-Blocksを使う

もっともシンプルな例

proc1は変数、よって「void (^)(void)」は型• ^がともかく「関数」ないしは「その始まり」•戻り値は^の左(この場合はvoid)•引数は^の右(この場合はなし)proc1だけではエラーは出ないが実行もされない•参照するだけで呼び出されないproc1()によって、{ ... }の部分を実行する

! void (^proc1)(void) = ^(void){ NSLog( @"==proc1=="); };! proc1;! proc1();

2010年11月26日金曜日

Page 5: Cocoa勉強会#43-Blocksを使う

引数があるBlocksの例

変数はproc2、型的なものは int(^)(id, int)• =より後は本体、最初に仮引数を定義•本体の定義には引数は不要

! 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

2010年11月26日金曜日

Page 6: Cocoa勉強会#43-Blocksを使う

Block内外での変数と変更可能性

__block宣言した変数はBlocks内で書き込める•そうじゃないものは書き込みができない

! __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'

2010年11月26日金曜日

Page 7: Cocoa勉強会#43-Blocksを使う

引数にBlocksをもつ関数を定義する

スケルトン• Blocksの引数の返り値はvoid•引数は「変数定義」と同じ形式関数の利用時•最初に紹介した基本型の右側と同じ

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 );

2010年11月26日金曜日

Page 8: Cocoa勉強会#43-Blocksを使う

引数に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日金曜日

Page 9: Cocoa勉強会#43-Blocksを使う

関数定義と長過ぎる引数

分け分からん…

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日金曜日

Page 10: Cocoa勉強会#43-Blocksを使う

マクロ定義で見やすくする

引数の並びを仮引数込みでマクロ定義する•それを利用して、スケルトン、インプリメンテーション、利用時、それぞれで利用する•スケルトンでは仮引数は無視されるので、指定してあっても問題ない

#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日金曜日

Page 11: Cocoa勉強会#43-Blocksを使う

Blocksの型定義

引数並び、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 );

2010年11月26日金曜日

Page 12: Cocoa勉強会#43-Blocksを使う

クラス定義で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日金曜日

Page 13: Cocoa勉強会#43-Blocksを使う

マルチタスク

NSThreadでマルチタスク•引数で渡したBlocksの実行がなんかおかしい•とりあえずはあきらめたが…NSInvocationOperation/NSBlockOperationがある• NSOperationの派生クラスなので、単純に言えばNSThreadの「今風」な使い方が可能• Blocksで渡したプログラムを、別スレッドで実行できた

2010年11月26日金曜日

Page 14: Cocoa勉強会#43-Blocksを使う

考察

APIにBlocksを使うものが出てきている• iOSのバックグランドタスクはこれしかない•避けて通れないJavaScriptほどの柔軟性はない•文字列変数からBlocks生成はできない文法がなんか腑に落ちるような落ちないような•パターンで学習するしかないかな~

2010年11月26日金曜日