语法
1,block的声明格式:
返回值类型(^block的名字)(参数类型1,参数类型2,.......)
2,block的定义格式:
^返回值类型(参数类型1 参数名,参数类型2 参数名.......){return 返回值类型;}
如:void(^myBlock)(int a);
typedef void(^blockType)(int a);//声明block类型为blockType
blockType myblock;//声明blcok变量 myblock
myblock = ^(int a){return a*a};//变量myblock赋值
myblock(2);//block调用
注:返回值类型是可以省略的
如:int (^add) (int,int) = ^(int number1,int number2){return number1+number2;}
typedef void (^blockType)(void)
- (void)method:(id)obj block:(blockType)block 或者
- (void)method:(id)obj block:(void(^)(void))block (参考UIView animation block)
[ obj method:obj block:^(void){ stat1;stat2; } ] (这里就是上面提到的匿名block)
三,基本用法
1,add(2,3);//输出5
2,Block在oc中也是一个对象,可以对其进行release,copy,retain等操作。
如[add copy];
3,闭包特性
void testBlock(){
int a =1;
int b = 3;
int(^sum)(void) = ^{
return a + b;
};
printf(@"%d",sum);//输出是4;
a = 2;
printf(@"%d",sum);//输出仍是4;
};
原因:a和b都是自由变量或者local变量,在block中是只读的。在定义sum的时候,编译器已经对a和b做了一个const拷贝,不能在sum中修改a的值并保存。
4,如果想在block中修改外部自由(local)变量,一是可以引用_block修饰,二是可以用static改成全局变量。这时自由变量是可写的
void testBlock(){
_block int a =1;
int b = 3;
int(^sum)(void) = ^{
return a + b;
};
printf(@"%d",sum);//输出是4;
a = 2;
printf(@"%d",sum);//输出仍是4;
};
四,blocks的应用
1,用作多线程的代码单元(GCD),多核并行编程。
2,用作某个函数调用完成后的回调函数。如UIView动画,Notification。
Block作为回调函数比传统回调函数的优越性:
在函数调用的时候,将block作为一个参数传递,使得代码紧凑,结构清晰。
例如:
block之前,
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification object:nil];
}
- (void)keyboardWillShow:(NSNotification *)notification {
// Notification-handling code goes here.
}
block之后,
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardWillShowNotification
object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
// Notification-handling code goes here.
}];
}
3,允许访问本地变量,这样可以避免通过结构体将本地变量封装后传递给回调函数。最为典型的就是异步数据下载后,更新ui。
NSString* parameter = [self getSomeParameter];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{NSString* result
= [self fetchResultFromWebWithParameter:parameter];
dispatch_async(dispatch_get_main_queue(), ^{[self updateUIWithResult:result]; // 能直接使用上层block中的变量result,只读的。所以说可以直接使用局部变量});
}); |