这是我参与「第四届青训营 」笔记创作活动的的第7天
闭包与Objective-C block | 青训营笔记
闭包
什么是闭包(closure)
闭包 ≈ 保存函数+函数所在环境的结构体
闭包中的环境
环境 = 约束变量(局部变量、传入的参数) + 自由变量(函数体外部定义的变量)
自由变量的确定
一般由语言设计者决定,也可由用户自行指定,如OC中不同类型的闭包
OC中的闭包
OC中闭包是由Block实现的
Block基础
Block本质:一种数据类型,类似函数指针,可以用来传回调函数
- 本质:内存变量
- 存储一段代码,可以有参数,可以有返回值
- 声明
- 指定参数返回值的个数和类型,只能存储
- 返回值类型 (^block变量名) (参数列表)
- void (^myBlock1)();
- 初始化
- Block变量名 = ^返回值类型(参数列表){代码;}
- 调用:
- Block变量名()
- 简写
- 代码段:
- 没有返回值可以省略void
- void (^myBlock1)() = ^(){};
- 没有参数可以省略()
- void (^myBlock1)() = ^{};
- 有返回值也可以省略返回值类型
- 没有返回值可以省略void
- 声明:
- 可以只写类型,不写名称
- 代码段:
- 使用typedef简写block:
- typedef 返回值类型 (^block类型名)(参数列表);
- eg
- typedef void(^NewType)();
- NewType a = ^void{};
- Block访问外部变量
- Block代码块内部,可以取外部的局部变量和全局变量,但不能修改局部变量的值
- 可以修改的局部变量:用__block修饰局部变量
- Block作为函数的参数
- 回调函数
- Block作为函数的返回值
Block类型:
- 全局block
- NSGlobalBlock
- 保存在数据段
- 条件:定义在全局区/没有访问自动局部变量
- 栈block
- NSStackBlock
- 访问了自动局部变量
- 开启ARC时,有时会自动转为堆block
- Block作为函数返回值
- 将Block赋值给strong指针
- Block作为某些系统方法参数时
- 堆block
- NSMallocBlock
- 条件:通过调用stackblock的copy方法,生成的
block闭包的引用方式
- 值引用
- 基础类型:默认是值引用
- 对象:默认也是值引用,拷贝的是指针的地址
- 名称引用
-
__block修饰符后,block内变为名称引用(地址)
-
对象属性,因为保存的是self,属性是在运行时通过发送消息获取的
-
block中的循环引用问题
- self持有block、block内持有self
- 通过__weak和__strong解决
通过block实现链式调用
- 类实现方法,方法的返回值是block,block的返回值是类的实例(self),如Calculator.add
- 在block中进行操作,可以通过其他属性记录操作结果,如cal.result
- 初始化实例cal,cal.add是一个block,cal.add(2)对cal.result进行操作,返回cal,可以链式调用其他方法
- block实现异步操作
- GCD(Grand Central Dispatch)中dispatch_async/dispatch_after
- block本质还是一个对象
- 释放时机和普通变量一样