Block定义
块与函数相似,是可以获取其他函数局部变量的匿名函数。
Block写法
(1) 无参数
void(^block名)() = ^{代码块};
(2)有参数
void (^block名称)(参数列表) = ^(参数列表) { 代码实现};
(3)有参数 和 返回值 的
返回类型 (^block 名称)(参数列表) = ^(参数列表){代码实现};
(4)调用block保存的代码
block变量名(实参);
(5)typedef简化Block的声明、作为属性
声明:typedef return_type (^BlockTypeName)(var_type);
属性: @property (nonatomic, copy) BlockTypeName blockTypeName;
Block应用场景
1.响应事件
2.传递数据
如果block访问的外部变量是局部变量,那么就是值传递,外界改了,不会影响里面
如果block访问的外部变量是__block或者static修饰,或者是全局变量,那么就是指针传递,block里面的值和外界同一个变量,外界改变,内部也改变;
Block内存管理
(1)无论当前环境是ARC 还是 MRC,只要block没有访问外部变量,block始终在全局区;
(2)MRC情况下:
1.block如果访问外部变量,block在栈里
2.不能对block使用retain,否则不能保存在堆里
3.只有使用copy,才能放到堆里
ARC情况下:
1.block如果访问外部变量,block在堆里
2.block可以使用copy和strong,并且block是一个对象
Block注意事项
(1)Block可以访问外部变量(局部变量不能修改)但是可以改变全局变量、静态变量、全局静态变量;
(2)如果需要在block内部修改局部变量的值,使用__block修饰符外部变量;
(3)在block内部使用外部指针会造成循环引用,需要使用__weak修饰外部指针
__weak typeof(self) weakSelf = self;
使用__weak,也会有一个隐患,在block内部如果调用了延时函数还使用弱指针会娶不到该指针,因为已经被销毁了,为了保证在block内不会被释放,我们添加__strong。更多的时候需要配合strongSelf使用:
__weak typeof(self) weakSelf = self;
self.testBlock = ^{
__strong __typeof(weakSelf) strongSelf = weakSelf;
[strongSelf test];
});
Block传值
有两个视图控制器 A 和 B,现在点击 A 上的按钮跳转到视图 B ,并在 B 中的textfield 输入字符串,点击 B 中的跳转按钮跳转回 A ,并将之前输入的字符串显示在 A 中的 label 上。也就是说 A 视图中需要回调 B 视图中的数据。
BViewController.h代码:
typedef void(^CallBackBlcok) (NSString *text);
@interface BViewController : UIViewController
@property (nonatomic,copy)CallBackBlcok callBackBlock;
@end
BViewController.m代码:
- (IBAction)click:(id)sender {
self.callBackBlock(_textField.text);
[self.navigationController popToRootViewControllerAnimated:YES];
}
AViewController.m代码:
- (IBAction)push:(id)sender {
BViewController *bVC = [BViewController alloc]init];
__weak AViewController *weakSelf = self;
bVC.callBackBlock = ^(NSString *text){
NSLog(@"text is %@",text);
weakSelf.label.text = text;
};
[self.navigationController pushViewController:bVC animated:YES];
}