IOS 拾遗程序员iOS进阶之路

(三)Block之截获变量和对象

2017-10-21  本文已影响22人  madaoCN

相关文章


捕获自动变量

int i = 0;//自动变量
void (^blk)() = ^() {
    printf("%d", i);
};
blk();

经过转换代码后的部分源代码

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  int i; //需要注意
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _i, int flags=0) : i(_i) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
// Block方法指针
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
        int i = __cself->i; // bound by copy 需要注意
        printf("%d", i);
 }
// 构造函数的调用
__main_block_impl_0 blk = __main_block_impl_0(
                            __main_block_func_0, 
                            &__main_block_desc_0_DATA, 
                            i);

可见,自动变量i被追加到了__main_block_impl_0结构体中(如果Block语法中没有使用自动变量,则不会被追加)
在构造函数调用时候自动变量i也被当做参数传入了构造方法中
那么可知__main_block_impl_0被初始化为如下:

impl.isa = &_NSConcreteStackBlock;
impl.Flags = 0;
impl.FuncPtr = __main_block_func_0;
Desc = & __main_block_desc_0_DATA;
i = 0;

然后,将关注点放在Block方法指针上

 int i = __cself->i; 

执行Block语法时候,将__main_block_impl_0捕获的自动变量,被赋值给了内部新定义的变量

总的来说 “截获自动变量”意味着 将即将使用的变量保存到Block结构体实例中

捕获对象

id array = [[NSMutableArray alloc] init];
void (^blk)() = ^() {
     [array addObject:@"obj"];
     printf("%lu", (unsigned long)[array count]);
};
blk();

经过转换代码后的部分源代码

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  __strong id array; //注意这里
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __strong id _array, int flags=0) : array(_array) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
        __strong id array = __cself->array; // bound by copy
       [array addObject:@"obj"];
       printf("%lu", (unsigned long)[array count]);
}

static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) 
{
        _Block_object_assign((void*)&dst->array, 
                                     (void*)src->array,       
                                     3/*BLOCK_FIELD_IS_OBJECT*/);
}

static void __main_block_dispose_0(struct __main_block_impl_0*src)
 {  
        _Block_object_dispose((void*)src->array, 
                               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
};
函数 调用时机
__main_block_copy_0 Block从栈复制到堆
__main_block_dispose_0 堆上Block被废弃

那么什么时候栈会被复制到堆呢?

上一篇下一篇

猜你喜欢

热点阅读