以下是个人对block的理解:
虽没有更深入的了解内部实现机理,但总结了block的的使用,和个人理解
对block使用不熟练或者入门的童鞋们来说应该有所启发
demo 下载地址: Block demo
block定义的形式是这个样子:
return_type (^block_name)(parameters)
return_type 就是返回值类型,当然没有返回值的时候,为void
里面的^ 这个符号就是block的代表,他就是用来定义block的
name 就是定义的block 的名称
parameters 就是参数
2.
可以定义带参数的,可以不带,可以有返回值,也可以没有
eg: void(^Compeletion)(Bool success) // 带参数 参数传入是否完成
eg: void(^Compeletion)() // 不带参数 只是单纯的告诉你完成了
eg: Bool(^Compeletion)(Bool success) // 带参数 带返回值
eg: Bool(^Compeletion)() // 不参数 带返回值
3.
block 就是一个对象(貌似是:指向结构体的指针,所以可以理解是对象),所以它是占用内存的,在它所在的内存中,保存着block自身的实现函数,这一点是很重要的。这就是为什么我们写的block无论在什么地方实现,都能被执行的原因。
来构想一下步骤:
1》声明一个block void(^Compeletion)(Bool success);
2》实现这个block
Completion = ^(Bool success){
NSLog(@“%d”,success); };
3》 然后会自动 将花括号内部的所有代码 NSLog(@“%d”,success); 保存在block的内存中
4》等到你要使用的时候,就执行保存的代码
5》至于我们经常用来跨文件调用,在其他的类里面使用。 你就要保证这个block会在你要使用的时间之内不会被释放掉就行了。所以我们经常会把block做属性,只要他所在的对象不被销毁,他就存在,
4.
当block捕获了一个对象时,它会自动对其进行retain操作,所以我们经常使用的时候,要避免循环引用,ARC下 加 __weak 。避免他对他内部扑捉到得对象的强引用
eg: 对象 Person onePerson; 计数器是 1
在block中用 onePerons 的话,计数器 加1 变成 2
即便block外部release 了, onePerson 还是没有被释放掉,内存泄露
5.
Block的类型 block 共有三种类型
stack block 栈区
可以理解是一个函数的内部,出了函数内部就失效
heap block 堆区
堆区,可以用来长时间的保存,比如说把它当做属性(copy),只要对象不被release掉,这个block就不会失效,并且也可以用来跨文件使用。
grobal block 全局
全局 blcok与之前的stack block 、 heap block 不同,当一个block在闭包中不捕获程序的任何上下文(如各种程序中的变量)时,编译器在编译阶段就能够知道这个block执行的所需要的所有信息,这时,block会当做全局变量保存在全局内存中,以相当于单例的形式存在,它将不会收到任何release消息。
6. 使用
1》注意避免循环引用,前面说到,block 会将内部的对象引用计数器加1,所以处理不好会造成循环引用,在引用的对象前面 用 __weak 修饰就可以了
eg:__weak typeof(self) weakSelf = self;
2》属性修饰符 用copy修饰
7.定义 使用 typedef 修饰
/**
* 声明一个block
*
* @param leftTime 剩余的时间
*/
typedef void(^TimerLeftTime) (NSInteger leftTime);
demo 下载链接
欢迎留言继续探讨