block的定义:“带自动变量的匿名函数”
(一)写法:
^ void (int iAge){ NSLog(@"%d", iAge);};
和C函数写法区别在于:
1) :以插入符号 ^ 开始.
2):没有函数名字
当block声明变量时候的写法
void (^blk)(int iAge)
block 做函数参数时候
void testFunction:(int)age complete:(void(^)(int iAge))complete{ age++; if(complete){ complete(age); } }
(二)block是c语音的扩展,实际上block会被翻译成c语言的static 结构体和static方法,这就是为什么block能截获自动变量的原因。
-(id)init{ if (self = [super init]) { int iTmp = 0; ^(int i){ iTmp = 10; }; } return self; } 修改变量编译报错 修改为 -(id)init{ if (self = [super init]) { __block int iTmp = 0; ^(int i){ iTmp = 10; }; } return self; }
(三)关于block循环引用导致内存泄漏
1):block中使用到类的strong类型变量以及使用到self ,会导致内存泄露。一般解决办法
a:开启ARC 使用__weak 临时变量做转存。
@interface MyTest:NSObject{ strong id param; }
- (id)init{ if(self = [super init]){ ^(){ NSLog(@"%@", self); NSLog(@"%@", param);//XCode也会报告警告的,提示有循环引用 } } } //修改如下 - (id)init{ if(self = [super init]){ __weak id tmp = param; __weak id selfTmp = self; ^(){ NSLog(@"%@", selfTmp); NSLog(@"%@",tmp);//XCode也会报告警告的,提示有循环引用 } } }
b:若ARC关闭了,可使用__block类型临时变量,再在block中把临时变量赋值为nil,只是必须调用该block,不然一样会内存泄漏
- (id)init{ if(self = [super init]){ __block id tmp = param; void (^blk)() = ^(){ NSLog(@"%@",tmp); tmp = nil; } } }
循环引用的原因在于有strong 修饰的自动变量会被复制到堆上,copy.
在关闭ARC,需要手动 Block_copy() block 和Block_relase()