本文将介绍一下block的反向传值以及block使用的注意事项。
1.block定义
一般在.h文件中用如下方式定义。
typedef returnType(^name)(arguments);
returnType参数:表示block代码块返回值,若没有返回值则为void,若有返回值,则根据返回值类型来决定
name参数:block代码块的名称,可自己命名
arguments参数:反向传值的参数,可多个,用逗号隔开
例:
typedef void(^callBackBlock)(NSString* str,int num);
2.提供block访问接口
接下来需要在.h文件中设置block属性,以提供接口给其他控制器访问。@property (copy , nonatomic) callBackBlock myCallBackBlock;
在调用block块之前,要先判断该block是否被引用。block块的括号内加入所传参数,参数类型需要符合自定义block时的传值类型
- (void) popViewController
{
if (self.myCallBackBlock)
{
self.myCallBackBlock(@"My block",1010);
}
[self.navigationController popViewControllerAnimated: YES];
}
实现viewController01中的block
- (void) push
{
ViewController01* vc = [[ViewController01 alloc] init];
vc.myCallBackBlock = ^(NSString* str1,int num){
NSLog(@"%@ , %d",str1,num);
};
[self.navigationController pushViewController:vc animated:YES];
}
打印得到:
2015-02-06 10:40:40.428 OC_Test[1960:92579] My block , 1010
5.block中调用方法造成retain cycle
block会隐式地对进入其作用域内的对象(或者说被Block捕获的指针指向的对象)加retain,来确保Block使用到该对象时,能够正确的访问。
这样的代码是错误的:
ViewController01* vc = [[ViewController01 alloc] init];
vc.myCallBackBlock = ^(NSString* str1,int num){
[vc test];
};
vc在初始化的时候,retainCount为1。block中调用vc的test方法时,block会对vc再次retain,vc的retainCount变为2。ARC工程在合适的时候肯定会做一次隐式release或autoRelease,显然vc在release后的retainCount等于1,系统无法释放vc这部分资源(retainCount为0的时候才会释放),造成内存泄露。
正确写法:
ViewController01* vc = [[ViewController01 alloc] init];
// 1.block中引用到的变量为了防止造成retain cycle,加__weak弱引用修饰
__weak ViewController01* weakVc = vc;
vc.myCallBackBlock = ^(NSString* str1,int num){
// 2.为了避免多线程操作中弱引用提前释放
ViewController01* strongVc = weakVc;
[strongVc test];
};
有人会问了,为什么在block内用了强引用strongVc而不会造成retain cycle呢?简单来讲,strongVc是block内定义的变量,block不会对他再retain一次。而对于在block内中引用外部的变量,block才会对该变量自动retain。