iSO底層原理 - Block的本質(zhì)

Block的本質(zhì):
  • block本質(zhì)上也是一個OC對象,它內(nèi)部也有個isa指針;
  • block是封裝了函數(shù)調(diào)用以及函數(shù)調(diào)用環(huán)境的OC對象;

Block的數(shù)據(jù)結(jié)構(gòu)
Block的數(shù)據(jù)結(jié)構(gòu)

block的變量捕獲(capture)
  • 為了保證block內(nèi)部能夠正常訪問外部的變量,block有個變量捕獲機(jī)制;
    1.局部變量需要捕獲;
    2.全局變量不需要捕獲,直接訪問就可以。

  • 捕獲機(jī)制
局部變量
        // auto:自動變量,離開作用域就銷毀
        //默認(rèn)就是auto
        auto int age = 10; 
        static int height = 10;
        void (^block)(void) = ^{
            // age的值捕獲進(jìn)來(capture)
            NSLog(@"age is %d, height is %d", age, height);
        };
        age = 20;
        height = 20;
        block();
  • 打印結(jié)果是:age = 10; height = 20。
  • 底層結(jié)構(gòu)如下:
struct __test_block_impl_0 {
  struct __block_impl impl;
  struct __test_block_desc_0* Desc;
  int age;
  int *height;
  __test_block_impl_0(void *fp, struct __test_block_desc_0 *desc, int _age, int *_height, int flags=0) : age(_age), height(_height) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

1> 創(chuàng)建block的時候,直接 auto修飾 的age封裝到了block中了,block外再修改,不會影響block內(nèi)部的age;
2> static修飾的height,傳到block內(nèi)部的是一個指針;外部修改,也會影響block內(nèi)部的結(jié)果。

為何這樣設(shè)置 ?
  • 因為 auto修飾的局部變量,離開作用域后就會銷毀;如果也采用指針訪問,那此時訪問到的就是垃圾數(shù)據(jù)。
擴(kuò)展 :self 會被捕獲嗎 ?
- (void)test {
    void (^block)(void) = ^{
        NSLog(@"-------%p", self);
    };
    block();
}
  • 會;
  • self其實是一個參數(shù),參數(shù)是一個局部變量。
// test函數(shù)完整寫法如下:
- (void)test(Object *self, SEL _cmd) {
}


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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