一:基本定义
/*初步上式block定义的一些理解和解释,接下来会详解:
*block名为myBlock,结合C的函数指针,myBlock为block体的指针,指向block体的入口地址
*int result = myBlock(5) <==> ^(int num){return num*num}(5)//将5传给num
*回调时可以将myBlock作为参数传入,也可以直接传入block体^(int num){…};//
*整个block体作为参数传入时,往往没有参数,只是进行延迟运算作用,因为定义了block内容
如果是暂时左值不需要的话,block是不执行的。
例:[request setFailedBlock:^{NSError *error = [request error]; };];
//如果不执行setFailedBlock方法时,后面的block是不执行的,只是静静地待在堆中,原理接下来会说到。
*/
二:block原理
首先介绍基本的block,将OC语言block改写成C语言的block
具体步骤:
我们通过IMP定义可以看出:
在main()函数中,block的返回值为(void(*)()),其实就是一个函数指针,所在在这种情况下,block就可以看做是匿名函数的函数指针来对待。
三:关键字__block
主要作用:1.block对外部变量是只读的,要变成可读可写,就需要加上__block
2.将栈中的block复制到堆上一份,从而避免了循环引用这个情况
将带有__block关键字的block进行OC->C语言转换:
四:存储类型
block的存储形态有三种:_NSConcretStackBlock(栈)、_NSConcretGlobalBlock(全局)、_NSConcretMallocBlock(堆)
要点一:当block在函数内部,且定义的时候就使用了函数内部的变量,那么这个 block是存储在栈上的。
要点二:当block定义在函数体外面,或者定义在函数体内部且当时函数执行的时候,block体中并没有需要使用函数内部的局部变量时,也就是block在函数执行的时候只是静静地待在一边定义了一下而不使用函数体的内容,那么block将会被编译器存储为全局block。
要点三:全局block存储在堆中,对全局block使用copy操作会返回原函数指针;而对栈中的block使用copy操作,会产生两个不同的block地址,也就是两个匿名函数的入口地址。
要点四:ARC机制优化会将stack的block,转为heap的block进行调用。
以下存储类题目摘自cocoaChina论坛: