iOS-三种类型Block

更新时间:2019-08-02 09:21:49点击次数:248次
block本质上也是一个OC对象,它内部也有个isa指针
block是封装了函数调用以及函数调用环境的OC对象
block是封装函数及其上下文的OC对象
查看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;
  // 构造函数(类似于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 {
  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;
        // 定义block变量
        void (*block)(void) = &__main_block_impl_0(
                                                   __main_block_func_0,
                                                   &__main_block_desc_0_DATA
                                                   );
 
        // 执行block内部的代码
        block->FuncPtr(block);
    }
    return 0;
}
第二部分:Block特点自动捕获变量
1

int a=10;
void (^Block)(void) = ^{
    NSLog(@"a:%d",a);
};
a = 20;
Block();
输出值为 a:10
原因:创建block的时候,已经把a的值存储在里面了。

 2

auto int a = 10;
static int b = 25;
void (^Block)(void) = ^{
    NSLog(@"a:%d,num:%d",a,b);
};
a = 20;
b = 11;
Block();
输出结果为:a:10,b:11
愿意:auto变量block访问方式是值传递,static变量block访问方式是指针传递
 clang编译以后的源码如下

int a = __cself->a; // bound by copy
int *b = __cself->b; // bound by copy
 
NSLog((NSString *)&__NSConstantStringImpl__var_folders_2r__m13fp2x2n9dvlr8d68yry500000gn_T_main_d2875b_mi_0, a, (*b));
int a = 10;
static int b = 25;
block = ((void (*)())&__test_block_impl_0((void *)__test_block_func_0, &__test_block_desc_0_DATA, a, &b));
 
a = 20;
b = 11;
上述代码可查看 static修饰的变量,是根据指针访问的

第三部分 Block类型
block的类型,取决于isa指针,可以通过调用class方法或者isa指针查看具体类型,最终都是继承自NSBlock类型

__NSGlobalBlock __ ( _NSConcreteGlobalBlock   0x1)
__NSStackBlock __ ( _NSConcreteStackBlock  0x7 )
__NSMallocBlock __ ( _NSConcreteMallocBlock  0x6)
指针在0x1是全局   0x6堆   0x7栈

int a = 1;
void (^block1)(void) = ^{
    NSLog(@"block1");
};
block1();
void (^block2)(void) = ^{
    NSLog(@"block2:%d",a);
};
block2();
NSLog(@"%@/%@/%@",block1,block2,[^{
    NSLog(@"block3:%d",a);
} class]);
输出结果:
<NSGlobalBlock   0x1887898789899>/<NSMallocBlock 0x697878979>/<NSStackBlock  0x7s87687686>

本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是一个个人学习交流的平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽,造成漏登,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

  • 项目经理 点击这里给我发消息
  • 项目经理 点击这里给我发消息
  • 项目经理 点击这里给我发消息
  • 项目经理 点击这里给我发消息