Block系列文章—————————————
Block笔记(1)—— 基本认识
Block笔记(2)—— 底层结构
Block笔记(3)—— 基础类型的变量捕获
Block笔记(4)—— Block的类型
Block笔记(5)—— 对象类型的auto变量捕获
Block笔记(6)— __block的深入分析
————————————————————
__block的使用场景
大家应该都知道,如果想在block内部修改从外部捕获的auto
变量的值,可以在该auto
变量定义的时候,加上关键字__block
。代码案例如下
#import <Foundation/Foundation.h>
typedef void(^CLBlock)(void);
int main(int argc, const char * argv[]) {
@autoreleasepool {
__block int a = 10;
int b = 30;
CLBlock myblock = ^{
a = 20;
NSLog(@"%d",b);
};
myblock();
NSLog(@"myblock执行完之后,a = %d",a);
}
return 0;
}
*********************运行结果*********************
2019-09-04 19:41:51.709406+0800 Block学习[29867:3904669] 30
2019-09-04 19:41:51.709706+0800 Block学习[29867:3904669] myblock执行完之后,a = 20
__block
只可以用来作用于auto
变量,它的目的就是为了能够让auto
变量能够在block内部内修改。而全局变量和static
变量本来就可以从block内部进行修改,因此__block
对它们来说没有意义,所以__block
被规定只能用于修饰auto
变量,这一点应该不难理解。
__block的本质
老套路,我们先通过终端命令xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main.cpp
来看一下__block
以及block在底层张什么样子。首先看看block的底层结构
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
int b;
__Block_byref_a_0 *a; // by ref
__main_block_impl_0(void *fp,
struct __main_block_desc_0 *desc,
int _b,
__Block_byref_a_0 *_a,
int flags=0) : b(_b), a(_a->__forwarding) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
为了比较,我特意加了一个int b
作为对比,顺便回顾一