码迷,mamicode.com
首页 > 其他好文 > 详细

block 结构(1)

时间:2014-07-25 16:41:12      阅读:413      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   color   os   文件   io   

一个block其实是一个对象,有他自己的属性,结构如下

bubuko.com,布布扣
  • isa指针,所有对象都有该指针,用于实现消息传递等功能(ias一般指向父类、元类)
  • flags,用于按bit位表示一些block的附加信息
  • reserved,保留变量。
  • invoke,函数指针,指向具体的block实现的函数调用地址。
  • descriptor, 表示该block的附加描述信息,主要是size大小,以及copy和dispose函数的指针。
  • variables,capture过来的变量,block能够访问它外部的局部变量,就是因为将这些变量(或变量的地址)复制到了结构体中。

     

我们借助  clang -rewrite-objc 命令反编译.m文件得到.cpp文件,.m包含以下代
-(void )test3{
    NSString *_person2=@"person2";
    NSLog(@"block init:%@,%p,%p",_person2,&_person2,_person2);
    void (^myBlock)(int) = ^(int num) {
        NSLog(@"block excuteing:%@,%p,%p",_person2,&_person2,_person2);
    };
    _person2=@"person22";
    NSLog(@"block excutebefore:%@,%p,%p",_person2,&_person2,_person2);
    myBlock(1);
    NSLog(@"block excuteafter:%@,%p,%p",_person2,&_person2,_person2);
}

 

得到部分源代码

 //这里应该是注册代码中的常量,下面会用到

#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)
static __NSConstantStringImpl __NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_0 __attribute__ ((section ("__DATA, __cfstring"))) = {__CFConstantStringClassReference,0x000007c8,"KDBlockTest dealloc",19};
static __NSConstantStringImpl __NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_1 __attribute__ ((section ("__DATA, __cfstring"))) = {__CFConstantStringClassReference,0x000007c8,"person2",7};
static __NSConstantStringImpl __NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_2 __attribute__ ((section ("__DATA, __cfstring"))) = {__CFConstantStringClassReference,0x000007c8,"block init:%@,%p,%p",19};
static __NSConstantStringImpl __NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_3 __attribute__ ((section ("__DATA, __cfstring"))) = {__CFConstantStringClassReference,0x000007c8,"block excuteing:%@,%p,%p",24};
static __NSConstantStringImpl __NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_4 __attribute__ ((section ("__DATA, __cfstring"))) = {__CFConstantStringClassReference,0x000007c8,"person22",8};
static __NSConstantStringImpl __NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_5 __attribute__ ((section ("__DATA, __cfstring"))) = {__CFConstantStringClassReference,0x000007c8,"block excutebefore:%@,%p,%p",27};
static __NSConstantStringImpl __NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_6 __attribute__ ((section ("__DATA, __cfstring"))) = {__CFConstantStringClassReference,0x000007c8,"block excuteafter:%@,%p,%p",26};
//这里就是block对象的结构
//imp:函数指针,指向具体block实现的函数
//_person2:截获的变量
//isa、flags、funcptr、desc后面会说道。
struct __KDBlockTest__test3_block_impl_0 {
  struct __block_impl impl;
  struct __KDBlockTest__test3_block_desc_0* Desc;
  NSString *_person2;
  __KDBlockTest__test3_block_impl_0(void *fp, struct __KDBlockTest__test3_block_desc_0 *desc, NSString *__person2, int flags=0) : _person2(__person2) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
//block实现的函数
static void __KDBlockTest__test3_block_func_0(struct __KDBlockTest__test3_block_impl_0 *__cself, int num) {

  NSString *_person2 = __cself->_person2; // bound by copy

        NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_3,_person2,&_person2,_person2);
    }
//copy函数,可以拷贝到堆上
static void __KDBlockTest__test3_block_copy_0(struct __KDBlockTest__test3_block_impl_0*dst, struct __KDBlockTest__test3_block_impl_0*src) {_Block_object_assign((void*)&dst->_person2, (void*)src->_person2, 3/*BLOCK_FIELD_IS_OBJECT*/);}
//对应的释放函数
static void __KDBlockTest__test3_block_dispose_0(struct __KDBlockTest__test3_block_impl_0*src) {_Block_object_dispose((void*)src->_person2, 3/*BLOCK_FIELD_IS_OBJECT*/);}
//block对象的描述信息(大小等等)
static struct __KDBlockTest__test3_block_desc_0 {
  size_t reserved;
  size_t Block_size;
  void (*copy)(struct __KDBlockTest__test3_block_impl_0*, struct __KDBlockTest__test3_block_impl_0*);
  void (*dispose)(struct __KDBlockTest__test3_block_impl_0*);
} __KDBlockTest__test3_block_desc_0_DATA = { 0, sizeof(struct __KDBlockTest__test3_block_impl_0), __KDBlockTest__test3_block_copy_0, __KDBlockTest__test3_block_dispose_0};
//这是objc测试函数test
static void _I_KDBlockTest_test3(KDBlockTest * self, SEL _cmd) {
    NSString *_person2=(NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_1;
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_2,_person2,&_person2,_person2);
    void (*myBlock)(int) = (void (*)(int))&__KDBlockTest__test3_block_impl_0((void *)__KDBlockTest__test3_block_func_0, &__KDBlockTest__test3_block_desc_0_DATA, _person2, 570425344);
    _person2=(NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_4;
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_5,_person2,&_person2,_person2);
    ((void (*)(__block_impl *, int))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock, 1);
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_6,_person2,&_person2,_person2);
}

 

简单分析:
 1).block初始化,结合构造函数:
__KDBlockTest__test3_block_impl_0(void *fp, struct __KDBlockTest__test3_block_desc_0 *desc, NSString *__person2, int flags=0) : _person2(__person2) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
void (*myBlock)(int) = (void (*)(int))&__KDBlockTest__test3_block_impl_0((void *)__KDBlockTest__test3_block_func_0, &__KDBlockTest__test3_block_desc_0_DATA, _person2, 570425344);
传入了参数:函数指针、block描述、外部变量_person2,这时候在block内部对_person2进行了深拷贝(其实我也没从哪里看出来到底是深拷贝,希望大神赐教)
2).执行block
((void (*)(__block_impl *, int))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock, 1);

其实还是调用了block函数指针 所指向的函数__KDBlockTest__test3_block_func_0,并把block自己作为参数传递进去。

static void __KDBlockTest__test3_block_func_0(struct __KDBlockTest__test3_block_impl_0 *__cself, int num) {
  NSString *_person2 = __cself->_person2; // bound by copy

        NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_3,_person2,&_person2,_person2);
    }

值得注意的的是,我们在执行之前对_person2修改,但是并没有对block内部产生影响,因为在构造block的时候,block内部对截获的变量已经做了深拷贝,执行block的时候,直接调用函数__KDBlockTest__test3_block_func_0,函数内部,是引用了block拷贝的_person2对象,我想这应该就是block截获变量的特性

block 结构(1),布布扣,bubuko.com

block 结构(1)

标签:des   style   blog   http   color   os   文件   io   

原文地址:http://www.cnblogs.com/NarutoYq/p/3867907.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!