iOS Block底层原理

iOS Block底层原理,第1张

block本质上也是一个OC对象
block 内部的isa指针继承自 NSObject,即可证明 block 即 OC 对象
block 是封装了函数调用以及函数调用环境的OC对象

1,定义一个block

int main(int argc, char * argv[]) {
    void (^myBlock)(void)=^{
        NSLog(@"====");
    };
    myBlock();
    return 0;
}

使用如下方式转换成cpp

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp

转换后的代码为

struct __block_impl {
  void *isa;
  int Flags;
  int Reserved;
  void *FuncPtr;
};
/*
该结构体内有2个结构体成员变量(iml、Desc),和一个与结构体同名的构造函数,函数返回值就是该结构体
所以(block定义简化表达式)void (*block)(void) = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA);中调用函数__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA)时,就会生成一个__main_block_impl_0结构体并返回。
*/
struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  __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;
  }
};
//__main_block_func_0 是 block 中封装的代码块,这里指的就是{NSLog(@"Hello, World!");}
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {

        NSLog((NSString *)&__NSConstantStringImpl__var_folders_2b_1fhvhw8972gfxd0j9_vwwj0r0000gn_T_main_2a1915_mi_0);
    }
//__main_block_desc_0_DATA是一个__main_block_desc_0类型的结构体变量,在声明时即进行赋值 *** 作,用于存放 block 的大小信息
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, char * argv[]) {

/*
block 定义简化解读void (*block)(void) = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA);
1、void (*block)(void)表示 block 是一个函数指针,函数名为block
2、=右边是指,将函数__main_block_impl_0的返回值,通过地址(&)符号,将函数的结果地址赋值给函数指针变量 block,但是一个是函数指针,一个结构体,不能直接赋值,所以原定义表达式中有将结构体地址值强转为函数指针类型的 *** 作((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));

*/

    void (*myBlock)(void)=((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));

/*
1、经过上述解析,我们知道 block 此时指向的是一个__main_block_impl_0结构体,结构体中的 impl结构体成员变量内有 Funcptr
2、为什么不是通过接构体一层层调用block->impl->FuncPtr呢?而是直接block->FuncPtr(block);调用?
3、通过前面的调用源码((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);可知,里面调用 FuncPtr 前会进行1层转换,即(__block_impl *)block后,block 从类型(void (*)()转为__block_impl类型,但我们知道,block 变量实际类型是__main_block_impl_0,所以从底层上说,block 的类型转换实际上应该是从__main_block_impl_0转到__block_impl
4、为甚么可以从__main_block_impl_0转到__block_impl呢?那时应为结构体的变量地址值实际等于该结构体第一个成员变量的地址值,而__main_block_impl_0结构体第一个成员变量就是__block_impl结构体,所以当要调用 FuncPtr 成员变量时,就是从地址值开始寻址,而从__main_block_impl_0开始寻址,和从__block_impl开始寻址,它们的起始地址值就是同一个。
5、FuncPtr 指向的是函数__main_block_func_0,在调用是需要将 block 作为参数传入。
*/
    ((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock);

    return 0;
}

2、局部int变量在block中的使用是值捕获,NSString是值拷贝

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  int value;局部变量
  NSString *str;局部变量
  //使用值捕获
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _value, NSString *_str, int flags=0) : value(_value), str(_str) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  int value = __cself->value; // bound by copy
  NSString *str = __cself->str; // bound by copy

        int a = value;
        NSString * st = str;
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_2b_1fhvhw8972gfxd0j9_vwwj0r0000gn_T_main_6d3cd7_mi_1);
    }
    static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->str, (void*)src->str, 3/*BLOCK_FIELD_IS_OBJECT*/);}

static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->str, 3/*BLOCK_FIELD_IS_OBJECT*/);}

static struct __main_block_desc_0 {
  size_t reserved;
  size_t Block_size;
  void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*);
  void (*dispose)(struct __main_block_impl_0*);
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0};
int main(int argc, char * argv[]) {

     int _staticValue = 10;
    NSString *str = (NSString *)&__NSConstantStringImpl__var_folders_2b_1fhvhw8972gfxd0j9_vwwj0r0000gn_T_main_991d3c_mi_0;
    void (*myBlock)(void)=((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, _staticValue, str, 570425344));

    ((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock);

    return 0;
}

3、static局部变量的地址

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  int *_staticValue;//局部static变量
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int *__staticValue, int flags=0) : _staticValue(__staticValue) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  int *_staticValue = __cself->_staticValue; // bound by copy

        int a = (*_staticValue);

        NSLog((NSString *)&__NSConstantStringImpl__var_folders_2b_1fhvhw8972gfxd0j9_vwwj0r0000gn_T_main_82eaea_mi_0);
    }

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, char * argv[]) {

    static int _staticValue = 10;
    void (*myBlock)(void)=((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, &_staticValue));//在这里直接传递了指针

    ((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock);

    return 0;
}

4、全局变量没有捕获行为

static int _staticValue = 10;
int puba = 100;


struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  __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;
  }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
//全局变量,在这里直接使用
        int a = _staticValue;
        int b = puba;
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_2b_1fhvhw8972gfxd0j9_vwwj0r0000gn_T_main_89e1fe_mi_0);
    }

5、block对oc对象是指针访问

6、__weak int a = 10,其实内部是创建一个对象,对象内部有一个同名的属性,初始化对象的时候,把局部变量的值设置给这个同名属性,然后把对象的地址传给了block内部

struct __Block_byref__staticValue_0 {
  void *__isa;
__Block_byref__staticValue_0 *__forwarding;
 int __flags;
 int __size;
 int _staticValue;
};

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  __Block_byref__staticValue_0 *_staticValue; // by ref
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref__staticValue_0 *__staticValue, int flags=0) : _staticValue(__staticValue->__forwarding) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  __Block_byref__staticValue_0 *_staticValue = __cself->_staticValue; // bound by ref


        (_staticValue->__forwarding->_staticValue) = 100;
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_2b_1fhvhw8972gfxd0j9_vwwj0r0000gn_T_main_e9c1f0_mi_0);
    }
static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->_staticValue, (void*)src->_staticValue, 8/*BLOCK_FIELD_IS_BYREF*/);}

static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->_staticValue, 8/*BLOCK_FIELD_IS_BYREF*/);}

static struct __main_block_desc_0 {
  size_t reserved;
  size_t Block_size;
  void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*);
  void (*dispose)(struct __main_block_impl_0*);
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0};
int main(int argc, char * argv[]) {
    __attribute__((__blocks__(byref))) __Block_byref__staticValue_0 _staticValue = {(void*)0,(__Block_byref__staticValue_0 *)&_staticValue, 0, sizeof(__Block_byref__staticValue_0), 10};

    void (*myBlock)(void)=((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref__staticValue_0 *)&_staticValue, 570425344));

    ((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock);

    return 0;
}

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/web/996810.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存