block相关 问答

1. block的本质和原理

  • block的本质实际上是OC对象,内部也存在着isa指针;

  • block 可作为代码块、函数的参数、返回值也可以代替代理;

  • block内部封装了函数调用地址 和 函数调用环境(函数的参数、所访问的外部属性值);

  • block底层是一个结构体(内部封装了函数调用地址 和 函数调用环境),结构体内部包含了两个结构体:

     struct __block_impl  impl;
     struct __main_block_desc_0 *Desc;
    

2.block中的循环引用

在 block(点语法)里面引用一个实例变量时,该实例对象会被 retain

解决循环引用的方式不同
MRC中使用__block(可修饰对象和基本数据类型)
ARC中使用 __weak(只可修饰对象)

3.为什么要用copy修饰

在MRC中,block默认是在栈上创建的。如果我们将它赋值给一个成员变量,如果成员变量没有被copy修饰或在赋值的时候没有进行copy,也就是局部变量离开作用域之后会被系统回收,那么在使用这个block成员变量的时候就会崩溃。

在MRC中, 定义Block属性时, 应该用copy修饰。在ARC中, 定义Block属性时, 系统会自动将其copy, 即复制到堆上.

用copy修饰的原因:block创建时默认是创建在栈上的, 超过作用域后就会被销毁, 只有使用copy才会生成一个堆block, 在作用域外被访问

4.block的类型

三种类型:
NSGlobalBlock:常量、静态创建的block
NSMallocBlock:在进程堆上分配的Block,动态创建的Block(引用外部常量或者变量的,MRC下调用copy的)。
NSStackBlock:进程栈上分配的Block,动态创建的Block。

void(^blockA)(void) = ^{
        NSLog(@"just a block");
    };
NSLog(@"%@", blockA);

int value = 10;
void(^blockB)(void) = ^{

    NSLog(@"just a block === %d", value);
};
NSLog(@"%@", blockB);

void(^ __weak blockC)(void) = ^{
    NSLog(@"just a block === %d", value);
};

NSLog(@"%@", blockC);

void(^ __weak blockD)(void) = ^{
    NSLog(@"just a block");
};

NSLog(@"%@", blockD);

2020-07-08 16:13:42.285554+0800 EAccountDemo[20034:4129159] <__NSGlobalBlock__: 0x1046351a0>
2020-07-08 16:13:42.285628+0800 EAccountDemo[20034:4129159] <__NSMallocBlock__: 0x281632be0>
2020-07-08 16:13:42.285688+0800 EAccountDemo[20034:4129159] <__NSStackBlock__: 0x16b90d1f0>
2020-07-08 16:13:42.285738+0800 EAccountDemo[20034:4129159] <__NSGlobalBlock__: 0x1046351e0>

你可能感兴趣的:(block相关 问答)