##Block的简介
Block是Objective-C中的一个对象,类似于C语言中的函数指针。与函数指针不同的时Block可以使用上下文中的变量,而函数指针只可以使用全局的变量和入参。
##Block的使用语法
Block可以命名,也可以直接使用未命名的Block对象,如下面示例,就是直接返回了一个未命名的Block对象:
下面一个例子则是先声明了一种Block对象的类型,再定义对应的Block对象:
##Block中得变量使用
Block中的变量主要是指上下文中得assign/retain/weak等类型的局部变量或成员变量的使用:
如上面示例中的使用,就是使用了默认assign类型的局部变量base,结果就等于203。因为Block对象在定义时对上下文中的变量进行了备份,所以base在执行Block时的值为200,输出就是203。因此,在Block的内部不能够对assign类型的变量进行修改,因为修改的时备份的值,对实际变量的值是修改无效的。
下面在定义base的时候加上__block,则返回的值为204。
原因就是使用block/weak定义的变量,Block在定义的时候并没有进行数值的备份,而是记录了类似于指针的地址,所以在后面执行Block的时候,用的值并不是定义时候获取的备份,而是该变量的实际数值。也因此,可以在Block内部对block/weak修饰的变量进行修改。
##retain cycle(引用嵌套)
retain cycle问题的根源在于Block和obj可能会互相强引用,互相retain对方,这样就导致了retain cycle,最后这个Block和obj就变成了孤岛,谁也释放不了谁。
举个简单地例子:
由于request和Block对象相互之间有强引用的关系,导致最后两者都无法释放。也就是Block对象释放必须先释放request,而request释放又必须先释放Block对象,最后都无法释放。
解决的办法就是在Block对象中对request进行弱引用,这样Block的释放就不依赖于request的释放,最后能够全部释放。
##Block使用对象被提前释放
Block使用对象被提前释放主要是由于开发者担心retain cycle错误的使用__block导致。
这里用dispatch_after模拟了一个异步任务,10秒后执行Block。但执行Block的时候MyClass* obj已经被释放了,导致crash。解决办法是不要使用__block。