声明:本文仅供记忆使用,并不适合新手小白观看
block本质上也是一个OC对象,它内部也有个isa指针
block的变量捕获
- 捕获机制

- auto变量捕获

block的类型
-
block有3种类型,可以通过调用class方法或者isa指针查看具体类型,最终都是继承自NSBlock类型
NSGlobalBlock (_NSConcreteGlobalBlock)全局区copy后什么也不做
NSStackBlock (_NSConcreteStackBlock)栈区copy后栈区到堆区
NSMallocBlock (_NSConcreteMallocBlock)堆区copy后引用计数加1 -
3种类型生成场景

block的copy
-
在ARC环境下,编译器会根据情况自动将栈上的block复制到堆上,比如以下情况
block作为函数返回值时- 将
block赋值给__strong指针时 block作为Cocoa API中方法名含有usingBlock的方法参数时block作为GCD API的方法参数时
-
MRC下block属性的建议写法
1
@property (copy, nonatomic) void (^block)(void);
-
ARC下block属性的建议写法
1
2@property (strong, nonatomic) void (^block)(void);
@property (copy, nonatomic) void (^block)(void);
对象类型的auto变量
当block内部访问了对象类型的auto变量时
- 如果block是在
栈上,将不会对auto变量产生强引用 - 如果block被拷贝到
堆上,会对auto变量产生强引用或弱引用会调用block内部的
copy函数->_Block_object_assign函数,函数会根据auto变量的修饰符(__strong、__weak、__unsafe_unretained)做出相应的操作,形成强引用(retain)或者弱引用 - 如果block从
堆上移除,自动释放引用的auto变量会调用block内部的
dispose函数->_Block_object_dispose函数,函数会自动释放引用的auto变量(release)
__block修饰符
- __block可以用于
解决block内部无法修改auto变量值的问题 - __block
不能修饰全局变量、静态变量(static) - 编译器会将
__block变量包装成一个对象
- 当block在
栈上时,并不会对__block变量产生强引用 - 当block被copy到
堆时,会对__block变量形成强引用(retain)会调用block内部的
copy函数->_Block_object_assign函数->强引用)
- 当block从
堆中移除时,自动释放引用的__block变量会调用block内部的
dispose函数->_Block_object_dispose函数,函数会自动释放引用的__block变量(release)
- __block中__forwarding指向

- __block变量对对象的引用和block对auto变量引用是一样的,详见上面对【#对象类型的auto变量】
解决block循环引用

参考资料
将oc代码转化为c++代码
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-8.0.0 main.m