因?yàn)樽髡咭彩亲罱艑lock來電,所以理解可能會(huì)有些偏差.首先大概說一下block是個(gè)什么東西.block就像是一個(gè)匿名函數(shù)(就是一個(gè)沒有名字的函數(shù)).他得強(qiáng)大之處在于他可以在兩個(gè)對象之間傳遞數(shù)據(jù).他比函數(shù)引用傳遞來說更加直觀.比如和協(xié)議相比.block是閉合執(zhí)行的,這樣使他更加能捕獲周圍環(huán)境的狀態(tài).重點(diǎn)說一下,他是OC的一個(gè)對象.
創(chuàng)建Block與調(diào)用
正如我前面所說,block像是一個(gè)匿名函數(shù),所以它能夠?qū)崿F(xiàn)函數(shù)的所有功能.但同時(shí)他又是一個(gè)OC對象,所以他的定義兼有兩種風(fēng)格
void (^block)() = ^{
NSLog(@"hello world");
};
我們看一下Block的具體定義,這個(gè)時(shí)候我們可以發(fā)現(xiàn),他跟函數(shù)的定義幾乎一模一樣,只不過多了個(gè)^,同時(shí)具有對象的特征可以賦值.上面的代碼的意思就是定義了一個(gè)返回值為空,名為block的block對象,他的功能是打印"hello world";至于調(diào)用,和c語言一樣直接
blockname(parameters list)
其實(shí)block的創(chuàng)建與調(diào)用沒什么難理解的,就是^讓人覺得很別扭,慢慢來,以后寫多了好了.
參數(shù)列表
正如上文而言,block當(dāng)然可以用參數(shù).看一個(gè)簡單的列子,這里沒什么好說的.直接上例子
void (^block)(NSString *) = ^(NSString *name){
NSLog(@"hello %@", name);
};
block(@"Steve");
多個(gè)參數(shù)的讀者自己腦補(bǔ)一下,我相信你可以的.
返回值
其實(shí)原本這個(gè)我打算直接寫寫出來的,但是考慮到跟C函數(shù)還是有一點(diǎn)出入,我這里還是跟大家寫明白點(diǎn).也希望能幫助到看篇文章的小白.在這里我要強(qiáng)調(diào)一點(diǎn),一定要類比C語言函數(shù),如果你是直接入手的OC建議你看一點(diǎn)C語言.
int (^sum)(int , int) = ^(int a, int b){
return a + b;
};
NSLog(@"%d", sum(1, 2));
閉合性
說到這個(gè)就有寫難以理解,所以我會(huì)在代碼演示之后談?wù)勛约旱目捶?先來看代碼
NSString *treat = @"Hi";
NSString *(^sayHi)(NSString *) = ^(NSString *name){
return [treat stringByAppendingFormat:@"%@", name];
};
NSLog(@"%@", sayHi(@"Steve")); //HiSteve
treat = @"Hello";
NSLog(@"%@", sayHi(@"Steve")); //HiSteve
從上面的運(yùn)行結(jié)果大家可以看到Block內(nèi)的非局部變量并沒有受到影響.其實(shí)這個(gè)實(shí)質(zhì)是當(dāng)?shù)谝辉L問treat時(shí)并不是直接引用的變量,而是將變量copy一份,以常量的形式保存到block中.這個(gè)時(shí)候大家明白為什么值不會(huì)改變了吧.
這個(gè)時(shí)候聰明的你會(huì)想,如果我向直接獲取block內(nèi)的值,并且不想用Block返回值的方式.這個(gè)時(shí)候我在教你一招,在變量的前面+__blcok,如下
__block int i = 0;
int (^count)() = ^ {
return i++;
};
NSLog(@"%d", count()); //0
NSLog(@"%d", count()); //1
NSLog(@"%d", count()); //2
在這里再說明一點(diǎn),因?yàn)閎lock在實(shí)際的運(yùn)行過程會(huì)出現(xiàn)向堆區(qū)拷貝的情況,所以通常情況下,block會(huì)產(chǎn)生一些額外的運(yùn)行的開銷.
明天還再說一下block做為類型和參數(shù)的使用.