Block

block从表面看相当于一个带有自动变量的匿名函数

因为block可以传入参数有并且有返回值

block里还能获取到外部的变量

但是默认block是不能修改局部变量的值

而且block捕获的是变量的瞬时的值

但是block可以修改静态变量、静态全局变量和全局变量

如果想要修改局部变量的值

需要在局部变量前面加一个__block

block只会捕获用到的变量

用不到的是不会捕获的

但是本质上是一个对象

因为还有一个isa的指针

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;//指向调用函数的地址
};

struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;//block描述信息
// 构造函数(类似于OC的init方法),返回结构体对象
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};

// 封装了block执行逻辑的函数
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {

NSLog((NSString *)&__NSConstantStringImpl__var_folders_2r__m13fp2x2n9dvlr8d68yry500000gn_T_main_c60393_mi_0);
}

static struct __main_block_desc_0 {
_t reserved;
size_t Block_size;//block的大小
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};
int main(int argc, const char * argv[]) {
/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
// 定义block变量
void (*block)(void) = &__main_block_impl_0(
__main_block_func_0,
&__main_block_desc_0_DATA
);

// 执行block内部的代码
block->FuncPtr(block);
}
return 0;
}

而且block可以作为一个参数也可以作为一个返回值还能当属性

block分三种

第一种NSGlobalBlock

NSGlobalBlock是位于全局区的block,它是设置在程序的数据区域(.data区)中

没有用到外界变量或只用到全局变量、静态变量的block为全局block

生命周期从创建到应用程序结束

第二种NSStackBlock

NSStackBlock是位于栈区是位于栈区,超出变量作用域,栈上的block以及__block变量都被销毁

用到局部变量、成员属性、变量的block为栈block

生命周期系统控制

函数返回即销毁

第三种NSMallocBlock

NSMallocBlock是位于堆区,在变量作用域结束时不受影响

有强指针引用或copy修饰的成员属性引用的block会被复制一份到堆中成为堆block

没有强指针引用即销毁

生命周期由程序员控制