NSString* (^myBlock)(NSString*, int); myBlock = ^(NSString *name, int age){ return [NSString stringWithFormat:@"My name is %@,I‘m %d years old!",name,age]; }; NSString *str = myBlock(@"胡曉偉",31); NSLog(@"%@",str);
上面的例子演示了Block的基本用法,Block聲明的基本結構是:
返回類型 (^變量名)(參數列表..)
例如:
void (^myBlock1)(void); //無返回值,無參數 void (^myBlock2)(NSObject, int); //有返回值,有參數 NSString* (^myBlock3)(NSString* name, int age); //有返回值和參數,並且在參數類型后面加入了參數名(僅為可讀性)
將一個Block定義為函數參數:
- (void)testBlock:(NSString *(^)(void)) myName { NSLog(@"My Name is %@",myName()); } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSString *(^myBlock)(void) = ^{ return @"wayne"; }; [self testBlock:myBlock]; return YES; }
下面看看如何通過Block訪問不同上下文環境的局部變量:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSString *str = @"AAA"; NSString *(^myBlock)(void) = ^(void){ return str; }; [self logBlock:myBlock]; return YES; } - (void)logBlock:(NSString *(^)(void))block { NSLog(@"%@",block()); }
下面的代碼測試了可變對象與不可變對象在Block中的情況:
NSString *str1 = @"str1"; NSMutableString *str2 = [NSMutableString stringWithString:@"str2"]; NSLog(@"************初始值與初始地址************"); NSLog(@"【%@】,【%p】",str1,&str1); NSLog(@"【%@】,【%p】",str2,&str2); void (^myBlock)(void) = ^{ NSLog(@"************Block中輸出************"); NSLog(@"【%@】,【%p】",str1,&str1); NSLog(@"【%@】,【%p】",str2,&str2); }; str1 = @"str1_update"; [str2 appendString:@"_update"]; NSLog(@"************更新后的值與地址************"); NSLog(@"【%@】,【%p】",str1,&str1); NSLog(@"【%@】,【%p】",str2,&str2); myBlock(); NSLog(@"************調用Block后的值與地址************"); NSLog(@"【%@】,【%p】",str1,&str1); NSLog(@"【%@】,【%p】",str2,&str2);
輸出結果:
************初始值與初始地址************ 【str1】,【0xbff4d1f8】 【str2】,【0xbff4d1f4】 ************更新后的值與地址************ 【str1_update】,【0xbff4d1f8】 【str2_update】,【0xbff4d1f4】 ************Block中輸出************ 【str1】,【0xbff4d1e4】 【str2_update】,【0xbff4d1e8】 ************調用Block后的值與地址************ 【str1_update】,【0xbff4d1f8】 【str2_update】,【0xbff4d1f4】
可以看出在Block內,不可變對象的值任然是初始化時的值,可變對象的值變成了新值。這是因為Block初始化在前,可變對象的修改在后;如果顛倒順序,先修改可變對象的值,再初始化Block,這樣Block就能同步修改后的值了。
最后看看Block對變量的訪問權限:
#import "AppDelegate.h" @interface AppDelegate () { NSString *str1; } @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSString *str2 = @"str2"; __block NSString *str3 = @"str3"; void (^myBlock)(void) = ^{ str1 = @"newString"; //ok //str2 = @"newString"; //error str3 = @"newString"; //ok NSLog(@"%@,%@,%@",str1,str2,str3); }; myBlock(); return YES; }
在Block里不能直接修改局部變量的值,如果要修改,需要在局部變量前加上修飾關鍵字__block。
從上面的例子可以看到在Block里能訪問並修改類變量、帶__block關鍵字的變量;但是不能修改不帶__block關鍵字的局部變量。