Block

結(jié)構(gòu)

struct __block_impl {
  void *isa;
  int Flags;
  int Reserved;
  void *FuncPtr;
};

int f1 = 55;
int f2 = 55;

struct __Block_byref_a1_0 {
  void *__isa;
__Block_byref_a1_0 *__forwarding;
 int __flags;
 int __size;
 int a1;
};

struct __Animal__init_block_impl_0 {
  struct __block_impl impl;
  struct __Animal__init_block_desc_0* Desc;
  int a2;
  Animal *self;
  int *c1;
  int *c2;
  __Block_byref_a1_0 *a1; // by ref
  __Animal__init_block_impl_0(void *fp, struct __Animal__init_block_desc_0 *desc, int _a2, Animal *_self, int *_c1, int *_c2, __Block_byref_a1_0 *_a1, int flags=0) : a2(_a2), self(_self), c1(_c1), c2(_c2), a1(_a1->__forwarding) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static int __Animal__init_block_func_0(struct __Animal__init_block_impl_0 *__cself, int te1, int te2) {
  __Block_byref_a1_0 *a1 = __cself->a1; // bound by ref
  int a2 = __cself->a2; // bound by copy
  Animal *self = __cself->self; // bound by copy
  int *c1 = __cself->c1; // bound by copy
  int *c2 = __cself->c2; // bound by copy

            (a1->__forwarding->a1) = a2;
            ((void (*)(id, SEL, int))(void *)objc_msgSend)((id)self, sel_registerName("setB1:"), ((int (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("b2")));
            (*c1) = (*c2);
            f1 = f2;
            return te1 + te2;
        }
static void __Animal__init_block_copy_0(struct __Animal__init_block_impl_0*dst, struct __Animal__init_block_impl_0*src) {_Block_object_assign((void*)&dst->a1, (void*)src->a1, 8/*BLOCK_FIELD_IS_BYREF*/);_Block_object_assign((void*)&dst->self, (void*)src->self, 3/*BLOCK_FIELD_IS_OBJECT*/);}

static void __Animal__init_block_dispose_0(struct __Animal__init_block_impl_0*src) {_Block_object_dispose((void*)src->a1, 8/*BLOCK_FIELD_IS_BYREF*/);_Block_object_dispose((void*)src->self, 3/*BLOCK_FIELD_IS_OBJECT*/);}

static struct __Animal__init_block_desc_0 {
  size_t reserved;
  size_t Block_size;
  void (*copy)(struct __Animal__init_block_impl_0*, struct __Animal__init_block_impl_0*);
  void (*dispose)(struct __Animal__init_block_impl_0*);
} __Animal__init_block_desc_0_DATA = { 0, sizeof(struct __Animal__init_block_impl_0), __Animal__init_block_copy_0, __Animal__init_block_dispose_0};

static instancetype _I_Animal_init(Animal * self, SEL _cmd) {
    self = ((Animal *(*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Animal"))}, sel_registerName("init"));
    if (self) {

        __attribute__((__blocks__(byref))) __Block_byref_a1_0 a1 = {(void*)0,(__Block_byref_a1_0 *)&a1, 0, sizeof(__Block_byref_a1_0)};
;
        int a2 = 0;
        static int c1 = 0;
        static int c2 = 0;
        int e1 = 10;

        int (*block)(int, int) = ((int (*)(int, int))&__Animal__init_block_impl_0((void *)__Animal__init_block_func_0, &__Animal__init_block_desc_0_DATA, a2, self, &c1, &c2, (__Block_byref_a1_0 *)&a1, 570425344));

        int g = ((int (*)(__block_impl *, int, int))((__block_impl *)block)->FuncPtr)((__block_impl *)block, e1, 20);
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_4m_xm_v2tn54_z1csnt42kykgmm0000gn_T_Animal_0d46d1_mi_0, g);
    }
    return self;
}



- (instancetype)init
{
    self = [super init];
    if (self) {
        
        __block int a1;
        int a2 = 0;
        static int c1 = 0;
        static int c2 = 0;
        int e1 = 10;
    
        int (^block)(int, int) = ^(int te1, int te2){
            a1 = a2;
            self.b1 = self.b2;
            c1 = c2;
            f1 = f2;
            return te1 + te2;
        };
        
        int g = block(e1, 20);
        NSLog(@"%d", g);
    }
    return self;
}

結(jié)論:

  1. 局部變量 a1, a2, 因?yàn)?a1用__block修飾, 所以捕獲a1的地址, a2只是訪(fǎng)問(wèn)變量, 所以直接捕獲a2的值.
    2.局部變量 self, 因?yàn)閎1和b2都是self的屬性, 所以直接捕獲了self.
  2. 靜態(tài)變量c1和c2是static修飾的, 捕獲了地址.
  3. 全局f1和f2, 沒(méi)有捕獲, 內(nèi)部直接訪(fǎng)問(wèn)的.

分類(lèi)

  • _NSConcreteGlobalBlock :全局Block。
    1. 內(nèi)部沒(méi)有使用auto類(lèi)型變量的block, 就是NSGlobalBlock類(lèi)型
    2. copy后仍然是全局block;
    3. NSGlobalBlock類(lèi)型的block, 不管怎樣類(lèi)型都不會(huì)改變, 依然在數(shù)據(jù)區(qū)
  • _NSConcreteMallocBlock:堆Block。
    1. 堆block會(huì)捕獲外部變量,存儲(chǔ)于內(nèi)存的堆區(qū)。
    2. copy后引用計(jì)數(shù) +1
  • _NSConcreteStackBlock:棧Block
    在ARC下, 一個(gè)NSStackBlock類(lèi)型的block被一個(gè)__strong類(lèi)型的指針引用時(shí), 系統(tǒng)會(huì)將block自動(dòng)復(fù)制到堆區(qū), 變成堆block, 此時(shí)如果block內(nèi)部訪(fǎng)問(wèn)的不是被__weak修飾的變量, 會(huì)引用計(jì)數(shù) + 1, 需要等到block超出作用域, 才會(huì)引用數(shù) - 1
    1. 內(nèi)部使用了auto類(lèi)型變量的block, 就是NSStackBlock類(lèi)型
    2. copy后生成堆block
      1. NSStackBlock類(lèi)型的block做為函數(shù)返回值時(shí), 會(huì)將返回的block復(fù)制到堆區(qū)
      2. NSStackBlock類(lèi)型的block賦值給__strong指針時(shí), 會(huì)將block復(fù)制到堆區(qū)
      3. block作為Cocoa API中方法名含有usingBlock的方法參數(shù)時(shí), block在堆區(qū)
      4. block作為GCD API的方法參數(shù)時(shí), block在堆區(qū)
調(diào)用 _Block_copy將 block 拷貝到堆上.
  • _Block_copy時(shí)候, 如果block需要釋放,則直接釋放
  • 如果block是globalBlock不需要copy, 直接返回.
  • 通過(guò)malloc申請(qǐng)內(nèi)存空間用于接收block, 通過(guò) memmove 將block拷貝至新申請(qǐng)的內(nèi)存中.
通過(guò)_Block_object_assign將Block 捕獲的外界變量拷貝到堆中.
  • 如果是普通對(duì)象,交給系統(tǒng)arc處理,拷貝對(duì)象指針,引用技術(shù)+1,外界變量不能釋放。
  • 如果是block類(lèi)型的變量,通過(guò)_Block_copy操作,將block從棧區(qū)拷貝到堆區(qū)
  • 如果是__block修飾的變量,調(diào)用_Block_byref_copy函數(shù),進(jìn)行內(nèi)存拷貝以及常規(guī)處理。
通過(guò) _Block_byref_copy 將 __block 修飾的變量拷貝到堆中
  • 將傳入的對(duì)象,強(qiáng)轉(zhuǎn)為Block_byref結(jié)構(gòu)體類(lèi)型對(duì)象。保存
  • 如果沒(méi)有將變量拷貝到堆上,就申請(qǐng)內(nèi)存進(jìn)行拷貝
  • 如果已經(jīng)拷貝,則進(jìn)行處理并返回
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容