iOS Block基本使用(一)

什么是Block?
Block 又稱為“塊” 或 “代碼塊”蜀细,作用是用來保存代碼恋昼,保存在其內(nèi)部的代碼塊 如果Block不被調(diào)用 這段代碼就不會(huì)執(zhí)行
在OC中Block的基本格式是這樣的

返回值類型  (^block名)  (參數(shù)類型 和 數(shù)量) = ^(形參 和 數(shù)量){   
   //code 
}队寇;

Block的本質(zhì)上也是一個(gè)OC對(duì)象 它內(nèi)部也有個(gè)isa指針
Block是封裝了函數(shù)調(diào)用以及函數(shù)調(diào)用環(huán)境(比如參數(shù)和返回值)的OC對(duì)象
Block是封裝了函數(shù)及其上下文的OC對(duì)象

1、寫一個(gè)簡單的block:

    @autoreleasepool {
        appDelegateClassName = NSStringFromClass([AppDelegate class]);
        MyBlock myBlock = ^{
        };
        NSLog(@"myBlock:%@",myBlock);//myBlock:<__NSGlobalBlock__: 0x10bfde038>
        myBlock();
    }

轉(zhuǎn)成底層代碼

typedef void(*MyBlock)(void);
//Block的本質(zhì)
struct __block_impl {
  void *isa;//isa指針(Block的類型-->指向Class)
  int Flags;
  int Reserved;
  void *FuncPtr;//封裝代碼塊的地址
};

struct __test_block_impl_0 {
  struct __block_impl impl;
  struct __test_block_desc_0* Desc;
// 構(gòu)造函數(shù)(類似于OC的init方法),返回結(jié)構(gòu)體對(duì)象
  __test_block_impl_0(void *fp, struct __test_block_desc_0 *desc, int flags=0) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __test_block_func_0(struct __test_block_impl_0 *__cself) {

}

static struct __test_block_desc_0 {
  size_t reserved;
  size_t Block_size;
} __test_block_desc_0_DATA = { 0, sizeof(struct __test_block_impl_0)};
void test(){
    MyBlock myBlock = ((void (*)())&__test_block_impl_0((void *)__test_block_func_0, &__test_block_desc_0_DATA));


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

}

2晴弃、block內(nèi)部捕獲變量

int a_q = 10;//全局變量
static int b_q = 10;//全局靜態(tài)變量
typedef void(^MyBlock)(void);
void test(){
    int a = 10;//局部變量
    static int b = 10;//局部靜態(tài)變量
    MyBlock myBlock = ^{
        NSLog(@"a=%d", a);//a=10
        NSLog(@"b=%d", b);//b=20
        NSLog(@"a_q=%d", a_q);//a_q=20
        NSLog(@"b_q=%d", b_q);//b_q=20
    };
    a = 20;
    b = 20;
    a_q = 20;
    b_q = 20;
    myBlock();
}

轉(zhuǎn)成底層代碼

typedef void(*MyBlock)(void);
//Block的本質(zhì)
struct __block_impl {
  void *isa;//isa指針(Block的類型-->指向Class)
  int Flags;
  int Reserved;
  void *FuncPtr;//封裝代碼塊的地址
};
int a_q = 10;
static int b_q = 10;
typedef void(*MyBlock)(void);

struct __test_block_impl_0 {
  struct __block_impl impl;
  struct __test_block_desc_0* Desc;
  int a;
  int *b;
  __test_block_impl_0(void *fp, struct __test_block_desc_0 *desc, int _a, int *_b, int flags=0) : a(_a), b(_b) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __test_block_func_0(struct __test_block_impl_0 *__cself) {
  int a = __cself->a; // bound by copy
  int *b = __cself->b; // bound by copy

        NSLog((NSString *)&__NSConstantStringImpl__var_folders_r0_rjxg_z6540vblvmqqv4klgsm0000gn_T_main_df2751_mi_0, a);
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_r0_rjxg_z6540vblvmqqv4klgsm0000gn_T_main_df2751_mi_1, (*b));
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_r0_rjxg_z6540vblvmqqv4klgsm0000gn_T_main_df2751_mi_2, a_q);
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_r0_rjxg_z6540vblvmqqv4klgsm0000gn_T_main_df2751_mi_3, b_q);
    }

static struct __test_block_desc_0 {
  size_t reserved;
  size_t Block_size;
} __test_block_desc_0_DATA = { 0, sizeof(struct __test_block_impl_0)};
void test(){
    int a = 10;
    static int b = 10;
    MyBlock myBlock = ((void (*)())&__test_block_impl_0((void *)__test_block_func_0, &__test_block_desc_0_DATA, a, &b));
    a = 20;
    b = 20;
    a_q = 20;
    b_q = 20;
    ((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock);
}

分析:
1纯路、局部變量a:可以看到我們Block內(nèi)部有一個(gè)(int _a)變量,局部變量a直接傳值給_a;(在局部變量中 auto局部變量出了作用域就會(huì)銷毀 為了避免執(zhí)行block時(shí) 變量不存在 所以auto變量在Block內(nèi)部被直接賦值為當(dāng)前值)
2或油、局部靜態(tài)變量b:可以看到我們Block內(nèi)部有一個(gè)(int _b)變量,局部靜態(tài)變量b把b(指針)傳給*_b;(static變量一直存在于內(nèi)存中不必有此擔(dān)憂,所以存儲(chǔ)的是變量指針驰唬,可以隨時(shí)取出最新值顶岸。)
3、全局變量a_q和全局靜態(tài)變量b_q:Block內(nèi)部沒有生成對(duì)應(yīng)的變量(如果是全局變量 Block使用時(shí)不用捕獲 直接訪問 所以得到的也全部都是最新值叫编。)
總結(jié):局部變量之所以需要捕獲 因?yàn)槲覀兪强绾瘮?shù)使用的 聲明和使用不是在一個(gè)作用域內(nèi)
注意:self這個(gè)變量也是局部變量 也會(huì)被block捕獲,因?yàn)樵贠C中所有的方法編譯后都是自帶兩個(gè)參數(shù) 一個(gè)是實(shí)例對(duì)象 一個(gè)是SEL _cmd
所以Block中如果用到self辖佣,self也會(huì)被捕獲。且Block內(nèi)部的self屬性 指向我們傳進(jìn)去的self
所以 我們也能理解為什么會(huì)造成循環(huán)引用了吧搓逾。

self捕獲

int a_q = 10;
static int b_q = 10;
typedef void(^MyBlock)(void);
- (void)test{
    int a = 10;
    static int b = 10;
    MyBlock myBlock = ^{
        NSLog(@"a=%d", a);//a=10
        NSLog(@"b=%d", b);//b=20
        NSLog(@"a_q=%d", a_q);//a_q=20
        NSLog(@"b_q=%d", b_q);//b_q=20
        NSLog(@"%@",self);
    };
    a = 20;
    b = 20;
    a_q = 20;
    b_q = 20;
    myBlock();
}

轉(zhuǎn)成底層代碼

int a_q = 10;
static int b_q = 10;
typedef void(*MyBlock)(void);

struct __ViewController__test_block_impl_0 {
  struct __block_impl impl;
  struct __ViewController__test_block_desc_0* Desc;
  int a;
  int *b;
  ViewController *self;
  __ViewController__test_block_impl_0(void *fp, struct __ViewController__test_block_desc_0 *desc, int _a, int *_b, ViewController *_self, int flags=0) : a(_a), b(_b), self(_self) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __ViewController__test_block_func_0(struct __ViewController__test_block_impl_0 *__cself) {
  int a = __cself->a; // bound by copy
  int *b = __cself->b; // bound by copy
  ViewController *self = __cself->self; // bound by copy

        NSLog((NSString *)&__NSConstantStringImpl__var_folders_r0_rjxg_z6540vblvmqqv4klgsm0000gn_T_ViewController_16af55_mi_0, a);
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_r0_rjxg_z6540vblvmqqv4klgsm0000gn_T_ViewController_16af55_mi_1, (*b));
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_r0_rjxg_z6540vblvmqqv4klgsm0000gn_T_ViewController_16af55_mi_2, a_q);
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_r0_rjxg_z6540vblvmqqv4klgsm0000gn_T_ViewController_16af55_mi_3, b_q);
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_r0_rjxg_z6540vblvmqqv4klgsm0000gn_T_ViewController_16af55_mi_4,self);
    }
static void __ViewController__test_block_copy_0(struct __ViewController__test_block_impl_0*dst, struct __ViewController__test_block_impl_0*src) {_Block_object_assign((void*)&dst->self, (void*)src->self, 3/*BLOCK_FIELD_IS_OBJECT*/);}

static void __ViewController__test_block_dispose_0(struct __ViewController__test_block_impl_0*src) {_Block_object_dispose((void*)src->self, 3/*BLOCK_FIELD_IS_OBJECT*/);}

static struct __ViewController__test_block_desc_0 {
  size_t reserved;
  size_t Block_size;
  void (*copy)(struct __ViewController__test_block_impl_0*, struct __ViewController__test_block_impl_0*);
  void (*dispose)(struct __ViewController__test_block_impl_0*);
} __ViewController__test_block_desc_0_DATA = { 0, sizeof(struct __ViewController__test_block_impl_0), __ViewController__test_block_copy_0, __ViewController__test_block_dispose_0};

static void _I_ViewController_test(ViewController * self, SEL _cmd) {
    int a = 10;
    static int b = 10;
    MyBlock myBlock = ((void (*)())&__ViewController__test_block_impl_0((void *)__ViewController__test_block_func_0, &__ViewController__test_block_desc_0_DATA, a, &b, self, 570425344));
    a = 20;
    b = 20;
    a_q = 20;
    b_q = 20;
    ((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock);
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
禁止轉(zhuǎn)載卷谈,如需轉(zhuǎn)載請(qǐng)通過簡信或評(píng)論聯(lián)系作者。
  • 序言:七十年代末恃逻,一起剝皮案震驚了整個(gè)濱河市雏搂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌寇损,老刑警劉巖凸郑,帶你破解...
    沈念sama閱讀 211,948評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異矛市,居然都是意外死亡芙沥,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來而昨,“玉大人救氯,你說我怎么就攤上這事「韬” “怎么了着憨?”我有些...
    開封第一講書人閱讀 157,490評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長务嫡。 經(jīng)常有香客問我甲抖,道長,這世上最難降的妖魔是什么心铃? 我笑而不...
    開封第一講書人閱讀 56,521評(píng)論 1 284
  • 正文 為了忘掉前任准谚,我火速辦了婚禮,結(jié)果婚禮上去扣,老公的妹妹穿的比我還像新娘柱衔。我一直安慰自己,他們只是感情好愉棱,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評(píng)論 6 386
  • 文/花漫 我一把揭開白布唆铐。 她就那樣靜靜地躺著,像睡著了一般羽氮。 火紅的嫁衣襯著肌膚如雪或链。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,842評(píng)論 1 290
  • 那天档押,我揣著相機(jī)與錄音澳盐,去河邊找鬼。 笑死令宿,一個(gè)胖子當(dāng)著我的面吹牛叼耙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播粒没,決...
    沈念sama閱讀 38,997評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼筛婉,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了癞松?” 一聲冷哼從身側(cè)響起爽撒,我...
    開封第一講書人閱讀 37,741評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎响蓉,沒想到半個(gè)月后硕勿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,203評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡枫甲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評(píng)論 2 327
  • 正文 我和宋清朗相戀三年源武,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了扼褪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,673評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡粱栖,死狀恐怖话浇,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情闹究,我是刑警寧澤幔崖,帶...
    沈念sama閱讀 34,339評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站跋核,受9級(jí)特大地震影響岖瑰,放射性物質(zhì)發(fā)生泄漏叛买。R本人自食惡果不足惜砂代,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望率挣。 院中可真熱鬧刻伊,春花似錦、人聲如沸椒功。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽动漾。三九已至丁屎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間旱眯,已是汗流浹背晨川。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評(píng)論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留删豺,地道東北人共虑。 一個(gè)月前我還...
    沈念sama閱讀 46,394評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像呀页,于是被迫代替她去往敵國和親妈拌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容

  • 目錄 Block概述 Block定義方式 Block保存代碼 Block傳值 Block對(duì)外部變量的傳遞 Bloc...
    子斌閱讀 1,389評(píng)論 2 7
  • 例行科普 Block 是 iOS4 之后添加的一種語法結(jié)構(gòu)蓬蝶,也成為閉包尘分,或者匿名函數(shù),在iOS開發(fā)過程中應(yīng)用較多丸氛,...
    CJ_BLUE閱讀 826評(píng)論 0 1
  • block作用:保存一段代碼1.block聲明2.block定義4.block類型5.block調(diào)用 開發(fā)中的使用...
    越天高閱讀 429評(píng)論 0 0
  • block在iOS日常開放中已經(jīng)越來越受歡迎了培愁,小結(jié)一下,填補(bǔ)之前遇到的坑 block block的作用:是用來保...
    追逐_chase閱讀 538評(píng)論 0 0
  • 1雪位、block的基本概念及使用 blcok是一種特殊的數(shù)據(jù)結(jié)構(gòu)竭钝,它可以保存一段代碼梨撞,等到需要的時(shí)候進(jìn)行調(diào)用執(zhí)行這段...
    __weak閱讀 557評(píng)論 0 2