美文网首页
block的原理是什么

block的原理是什么

作者: buding_ | 来源:发表于2024-05-16 10:46 被阅读0次

block的原理是什么

  • block本质上是一个OC对象,它内部也有isa指针
  • block是封装了函数调用以及函数调用环境的OC对象
看一下这个block被编译器转换后的底层结构:
int age = 5;
void (^block)(int, int) = ^(int a, int b) {
    NSLog(@"this is a block %d %d", a, b);
    NSLog(@"this is a block - %d",age);
};
block(10, 20);

block的底层结构:
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;
  int age;  //!!!!
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _age, int flags=0) : age(_age) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself, int a, int b) {
  int age = __cself->age; // bound by copy

            NSLog((NSString *)&__NSConstantStringImpl__var_folders_7h_7l3g9v_x21q8mng59_xy7cbm0000gn_T_main_579d88_mi_0, a, b);
            NSLog((NSString *)&__NSConstantStringImpl__var_folders_7h_7l3g9v_x21q8mng59_xy7cbm0000gn_T_main_579d88_mi_1,age);
        }

static struct __main_block_desc_0 {
  size_t reserved;
  size_t Block_size;
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};

int main(int argc, const char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
        int age = 5;
        void (*block)(int, int) = ((void (*)(int, int))&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, age));
        ((void (*)(__block_impl *, int, int))((__block_impl *)block)->FuncPtr)((__block_impl *)block, 10, 20);
    }
    return 0;
}
block结构.png

block的变量捕获

auto局部变量,捕获到block内部,值传递
static局部变量,捕获到block内部,指针传递
全局变量, 不会捕获到block内部,直接访问

self是一个局部指针(self是每个对象函数的隐藏参数),故在block中使用self是会捕获的

block的类型

_NSGlobalBlock_ (没有访问auto变量, 分配在数据段)
_NSStackBlock_ (访问了auto变量, 分配在堆区)
_NSMallocBlock_ (_NSStackBlock调用了copy, 分配在栈区)

内存分配.png

block使用auto变量

当block在栈上(_NSStackBlock_), 是不会对auto变量产生强引用

在block被拷贝堆上
会调用block内部的copy函数,
copy函数内部会调用_Block_object_assign函数:
_Block_object_assign会根据auto变量的修饰符(__strong,__weak,__unsafe_unretained)作出相对应操作,形成强引用(retain )或弱引用 (注意这里仅限ARC下,MRC下不会进行retain操作)

如果block从堆上移除
会调用block内部的dispose函数,
dispose函数会调用_Block_object_dispose函数:释放引用的auto变量,类似release

__block修饰符的作用

__block可以用于解决block内部无法修改auto变量值的问题
__block只能修饰auto变量
编译器会将__block修饰的变量,包装为一个对象;

struct __Block_byref_age_0 {
  void *_isa;
  __Block_byref_age_0 *__forwarding; 
  int __flags;
  int __size;
  int age;
}
//赋值操作
__Block_byref_age_0 *age = __cself->age;
(age->__forwarding->age) = 20;

-> 为什么__block修饰的变量可以被block中进行修改,本质上的原因是通过指针进行修改

当block在栈上, __forwarding指向自己
当block在堆上, __forwarding指向复制到堆上的__block结构体,而堆上的__forwarding指向自己
__weak typeof(self) weakSelf = self;
self.block = ^{
  __strong typeof(weakSelf) = sSelf; 
  -> 1-通过此方式可以直接调用成员变量 2-保证在执行block中该self的生命
 NSLog("%d",self->_age);
};

相关文章

  • Block 原理面试(1)

    玖:Block 原理面试(1) block的原理是怎样的?本质是什么?答:Block 的本质是一个封装了函数及其调...

  • OC语法 Block

    问题: Block的原理、本质是什么? Block的分类? Block的捕获机制? Blcok内部的内存管理? _...

  • block的本质1

    问题 block的原理是怎样的?本质是什么? __block的作用是什么?有什么使用注意点? block的属性修饰...

  • iOS底层第八、九、十天 -- Block

    引导语: Block原理是怎样的?本质是什么? _block的作用是什么?使用需要注意什么? block的属性修饰...

  • iOS底层原理总结 - 探寻block的本质(一)

    面试题 block的原理是怎样的?本质是什么? __block的作用是什么?有什么使用注意点? block的属性修...

  • iOS底层原理总结 - 探寻block的本质(一)

    面试题 block的原理是怎样的?本质是什么? __block的作用是什么?有什么使用注意点? block的属性修...

  • block

    block的原理是怎样的?本质是什么? __block的作用是什么?有什么使用注意点? block的属性修饰词为什...

  • iOS底层原理 - Block

    关于block的问题 1.block的原理是怎样的?本质是什么?2.__block的作用是什么?有什么使用注意点?...

  • block的理解

    1..block的原理是什么?本质是什么? block本质上也是一个OC对象,它内部也有个isa指针,block是...

  • IOS基础知识-block原理篇

    面试题 block的原理是怎样的?本质是什么?__block的作用是什么?有什么使用注意点?block的属性修饰词...

网友评论

      本文标题:block的原理是什么

      本文链接:https://www.haomeiwen.com/subject/gdhytjtx.html