1、什么是blocks:帶有自動(dòng)變量(局部變量)的匿名函數(shù)。
這里有兩個(gè)概念:自動(dòng)變量,匿名函數(shù)。
1.1)匿名函數(shù)(不帶名的函數(shù))
我們來看下函數(shù)指針的概念:
int func(int count);
int (*funcptr)(int) = &func; // 函數(shù)指針
int result = (*funcptr)(10); // 調(diào)用
可以看出上面func這個(gè)函數(shù)名是多余的,那我們可以去掉他嗎,這就要用到匿名函數(shù)。也就是blocks的概念。
自動(dòng)變量在下面會(huì)講到。
2、blocks語法
格式:^ 返回值類型 參數(shù)列表 表達(dá)式
其中畫橫線的兩個(gè)值都是可以省略的。
例子:^int (int count){return count+1;}
3、blocks變量
如上我們所說函數(shù)指針可以賦值給一個(gè)變量,同樣blocks也可以賦值給變量。
這是一個(gè)blocks函數(shù):^int (int count){return conunt+1;}
賦值給blocks變量:int(^blk)(int) = ^int (int count){return conunt+1;}
注意:blocks變量聲明的形式和函數(shù)指針很像。只是把*變成^。
既然blocks變量是一個(gè)“變量”,那么就擁有變量相應(yīng)的用法??梢援?dāng)作返回值、參數(shù)...
當(dāng)作返回值:
int (^func()) (int)
{
???? return ^(int count){return count+1;};
}
當(dāng)作參數(shù):
void func (int (^blk)(int)){.....}
上面就是blocks的基本用法,但是我們不會(huì)每次都輸入int(^blk)(int) 這么長(zhǎng)的變量吧,這也太長(zhǎng)了吧,也不好記住呀。下面用typedef改個(gè)名稱。
typedef int (^blk_t) (int); //這樣就可以了,blk_t =》int(^blk)(int)
上面代碼簡(jiǎn)寫一下:
void func (blk_t blk){...}
4、自動(dòng)變量的概念(局部變量)
int main()
{
??? int dmy = 256;
??? int val = 10;
??? const char *fmt = "val = %d \n";
??? void (^blk)(void) = ^{printf(fmt,val);}
??? val = 2; // 改變val值
??? fmt = "這些值改變?yōu)椋簐al = %d\n";
??? blk(); // 調(diào)用blocks
??? return 0;
}
猜一下上面的值輸出是10還是2呢? 結(jié)果是val = 10
這就涉及到一個(gè)概念“截獲自動(dòng)變量”。在blocks表達(dá)式里面保存的是該值的“瞬間值”,就像是照相機(jī)一樣,在那一瞬間保存了該變量,后面就算改寫了也不會(huì)影響blocks里面的值。
我們把blocks改寫成這樣:
void (^blk)(void) = ^{ val = 1; }
這樣是會(huì)報(bào)錯(cuò)的,我們不能改變?cè)撍矔r(shí)值。那么要怎么改呢??梢杂玫絖_block說明符。
改成這樣:就不會(huì)報(bào)錯(cuò)了。
__blcok int val = 10;
void (^blk)(void) = ^{ val = 1; }