Block介绍
在Objective-C中,Block是C语言扩充的功能。一句话总结Block就是:带有局部变量的匿名函数。实际上,Block语法在其他语言中也有,在Pythonh、LISP语言中叫Lambda(java 8也引入了),JavaScript中叫Anonymous Function,这种语言概念叫闭包(Closure)。
举个简单的例子:^(int count){NSLog("%d",count)},这就是一个简单的Block表达式。它没有函数名字,带有^符合。Block语法的范式如下:
^ 返回值类型 参数列表 表达式
^ int (int count){return count+1}
这其中的返回值可以省略:
^ 返回值类型 参数列表 表达式
此时,如果表达式总return 语句时,就使用该返回值的类型。没有return语句时就默认为void类型,表达式如下:
^ (int count){return count+1}
Block创建
可以使用typedef关键字,简便易读地声明一个Block变量,举例如下:
typedef int (^addMethodBlock)(int),这行代码声明了一个返回值为int类型,名字为addMethodBlock,参数为int类型的Block变量。然后可以给该变量赋值:
addMethodBlock=^ (int count){return count+1};
Block访问
Block体内访问局部变量,是copy变量的值,也就是说,Block体内访问局部变量,使用的是Block声明时变量的值,之后发生变化,Block体内依然保持不变。
Block体内不能修改局部变量的值,如果想要在Block体内修改,则需要在局部变量前面加入__block修饰符。
Block访问static修饰的变量时,直接读取变量的最新值,而不是在Block声明时候的值
为防止循环引用,需要在Block引用对象变量的时候加入以下代码
__weak typeof(self) weakSelf=self;
然后在block体里面用weakSelf来访问self里面的属性。
Block分类
什么,Block还有分类?是的,根据Block在内存中不同的位置,Block可以分为三类:
NSGloabBlock,NSStackBlock,NSMallocBlock
本质上,Block也是Objective-C的对象。有的对象存储在堆上,有的对象存储在栈上。存储在栈上的Block对象,属于NSStackBlock类型;存储在堆上的Block对象,属于NSMallocBlock类型;存储在程序的数据区域的Block对象,属于NSGloabBlock类型。
第一种,不需要在运行时改变行为的block,不需要放在堆或栈上,一个很简单的判别方法就是,是否引用外部变量
第二种,block是在栈上生成的,离开栈的作用域,block就无效了。在MRC环境下,需要手动的进行copy才能脱离栈使用。在ARC下,编译器自动进行copy操作
第三种,block是在堆上生成的,在第二种,copy过之后的block其实就是位于堆上,即变成了NSMallocBlock
网友评论