1. 程式人生 > >學習block時的一些筆記

學習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物件存在又不會造成迴圈引用。