学习block时的一些笔记

1.完整写法

void(^ blockName)(arg)=void^(arg){};

2.block 可以使用截取到的自动变量,但是不允许修改重新赋值。

例:

int m=3;

    char* str1="str1";

    void(^block1)(void)=^(){

      

        NSLog(@"%d,%s",m,str1);

    };

    m=6;

    str1="变化";

    block1();

OUTPUT:3,str1

若要修改自动变量的值必须添加__block

block以及截取自动变量的本质

使用clang -rewrite-objc 命令转化上面的代码

/**

 __block_impl 结构体

 */

struct __block_impl {

    void *isa;

    int Flags;

    int Reserved;

    void *FuncPtr;

};

/**

 __main_block_impl_0结构体  

 */

struct __main_block_impl_0 {

  //__block_impl 结构体

  struct __block_impl impl;

  //__main_block_desc_0 结构体

  struct __main_block_desc_0* Desc;

  int m;

  char *str1;

   

  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _m, char *_str1, int flags=0) : m(_m), str1(_str1) {

    //_NSConcreteStackBlock 用于初始化__block_impl 结构体的isa成员 表明该block类型为NSConcreteStackBlock

    impl.isa = &_NSConcreteStackBlock;

    impl.Flags = flags;

    impl.FuncPtr = fp;

    Desc = desc;

  }

};

/**

 1.变换后的block1 被作为简单的C语言函数来处理

 2.函数中的__cself 相当于OC中的self 这里指代__main_block_impl_0结构体的指针 

 ^(){

 int n=m+3;

 printf("%d,%s",m,str1);

 };

  */

static void __main_block_func_0(struct __main_block_impl_0 *__cself) {

  int m = __cself->m; // bound by copy 自动变量被保存到Block的结构体实例中。需要注意的是Block中不能直接使用C语言数据类型的自动变量,原因是C语言不允许这种操作

  char *str1 = __cself->str1; // bound by copy

        int n=m+3;

        printf("%d,%s",m,str1);

    }

/**

 __main_block_desc_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[]) {

    int m=3;

    char* str1="str1";

    /*

     void(^block1)(void)=^(){

    

     int n=m+3;

     printf("%d,%s",m,str1);

    

     };

     */

    void(*block1)(void)=((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, m, str1));

    m=6;

    str1="变化";

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

}

_ _block 修饰的变量 本质

例:__block int  m=3;此时m会被转化为__Block_byref_m_0结构体

struct __Block_byref_m_0 {

  void *__isa;

  __Block_byref_m_0 *__forwarding; (指向m:__Block_byref_m_0本身)

 int __flags;

 int __size;

 int m;// m=3

};

__Block_byref_m_0 *__forwarding;//持有指向该实例自身的指针,通过成员变量__forwarding访问成员变量val

解决循环引用问题
 

__weak typeof(_tom) weak = _tom;

   

    _tom.block = ^{

     

        __strong typeof(weak) strong = weak;

       

    };

__weak : 打破强引用链 即_tom对象强引用block对象,block对象强引用_tom对象

__strong:在block中声明了一个局部变量,暂时“强引用”_tom对象,由于block并不会强引用block内部声明的__strong修饰的局部变量。所以这样即保证了在block调用时_tom对象存在又不会造成循环引用。

猜你喜欢

转载自blog.csdn.net/qq_28117621/article/details/83995415