一、block的本质
1、block 本质就是OC对象
2、block是封装了函数调用以及函数调用环境的OC对象
3、block的底层结构如下图所示
block本质.png
二、block的类型
block 有三种类型分别如下:
__NSGlobalBlock__
__NSStackBlock__
__NSMallocBlock__
如何区分block的类型
只要没有访问 auto的变量 都是 __NSGlobalBlock__
访问了auto变量 但是没有调用 copy 都是 __NSStackBlock__
即访问了auto变量又调用了copy 则是 __NSMallocBlock__
注意:__NSGlobalBlock__即使调用了copy 它还是 __NSGlobalBlock__
__NSStackBlock__调用了 copy 它就变成了 __NSMallocBlock__
__NSMallocBlock__ 调用了copy 只是使引用计数增加 其类型还是 __NSMallocBlock__
注意:在ARC环境下,编译器会根据情况自动将栈上的block复制到堆上,比如以下情况
block作为函数返回值时
将block赋值给__strong指针时
block作为Cocoa API中方法名含有usingBlock的方法参数时
block作为GCD API的方法参数时
总结如下图所示:
block类型.png
三、block存储位置
如下图所示:
block存储位置.jpeg
1、程序区(代码区)存放工程中的代码
2、数据区 存放工程中的全局变量什么的
3、堆区 存放程序员手动开辟的空间 只要是 alloc 或则 malloc 开辟的空间都在堆区
4、栈区 存放程序员创建的局部变量等
注意:堆区的数据 不会随函数的结束而被释放 栈区的数据会随函数的结束而被释放
四、block 相关使用方法
1、ARC下block属性的建议写法
@property (strong, nonatomic) void (^block)(void);
@property (copy, nonatomic) void (^block)(void);
2、当block内部访问了对象类型的auto变量时
如果block是在栈上,将不会对auto变量产生强引用
3、如果block被拷贝到堆上
会调用block内部的copy函数
copy函数内部会调用_Block_object_assign函数
_Block_object_assign函数会根据auto变量的修饰符(__strong、__weak、__unsafe_unretained)做出相应的操作,形成强引用(retain)或者弱引用
4、__block的用法
__block可以用于解决block内部无法修改auto变量值的问题
__block不能修饰全局变量、静态变量(static)
编译器会将__block变量包装成一个对象
网友评论