Block對象是一個C底層的語法和運行時特性侥加,它和標(biāo)準(zhǔn)的C函數(shù)有點相似捧存,但除了可執(zhí)行的代碼它們包含變量自動綁定棧或在堆內(nèi)管理內(nèi)存担败。因此塊可以維護一系列的狀態(tài)-當(dāng)執(zhí)行時用于影響它的行為昔穴。
你可以使用塊去結(jié)合被傳給API的函數(shù)表達式,額外儲存 和被多線程使用提前。Block作為回調(diào)是十分有用的吗货,因為Block都攜帶被執(zhí)行的代碼在回調(diào)時,并且在執(zhí)行期間數(shù)據(jù)是必須的狈网。
Block在GCD和Clang是可用的宙搬,block運行時是開源的,在相關(guān)網(wǎng)站可以找到關(guān)于這個的有關(guān)內(nèi)容拓哺。
1勇垛,聲明和使用blocks
你可以用……操作符去聲明block變量今兒提示block字面值的開頭。block自身的body在{}內(nèi)士鸥,例如
int multiplier = 12;
int (^myBlock)(int) = ^(int num) {
return num * multiplier;
};
Note:int 指的是block的返回值類型闲孤,^表示這是一個block,而myBlock則表示聲明了一個變量*myBlock烤礁,而num則指的是帶一個參數(shù)讼积,而{}內(nèi)則是block的body。這是一個完整的block聲明與使用的例子脚仔。
2勤众,直接使用blocks
在許多時間中,不必聲明block變量鲤脏,相反你在要求作為參數(shù)的地方寫一個塊內(nèi)聯(lián)们颜。
char *myCharacters[3] = { "TomJohn", "George", "Charles Condomine" };
qsort_b(myCharacters, 3, sizeof(char *), ^(const void *l, const void *r) {
char *left = *(char **)l;
char *right = *(char **)r;
return strncmp(left, right, 1);
});
// myCharacters is now { "Charles Condomine", "George", "TomJohn" }
3,塊與cocoa
在cocoa 框架中吕朵,一系列的方法帶塊作為一個參數(shù),典型的要么去在對象的集合上去實現(xiàn)操作 要么在一個操作完成后作為一個回調(diào)使用掌桩,下面的例子展示如何使用帶有sortedArrayUsingComparator:的塊
NSArray *stringsArray = @[@"string1",@"string3",@"string4",@"string5"];
static NSStringCompareOptions comparisonOptions = NSCaseInsensitiveSearch | NSNumericSearch | NSWidthInsensitiveSearch | NSForcedOrderingSearch;
NSLocale *currentLocale = [NSLocale currentLocale];
NSComparator finderSortBlock = ^(id string1,id string2) {
NSRange string1Range = NSMakeRange(0, [string1 length]);
return [string1 compare:string2 options:
comparisonOptions range:string1Range locale:currentLocale];
};
NSArray *finderSortArray = [stringsArray sortedArrayUsingComparator:finderSortBlock];
NSLog(@"finderSortArray:%@",finderSortArray);
結(jié)果如下所示:
finderSortArray:(
string1,
string3,
string4,
string5
)
塊概念上的綜述
塊對象給我們提供了一個方式去在C語言和C衍生的語言中生成一個特殊的函數(shù)體作為表達式边锁,例如OC,C++。在其他語言和環(huán)境中波岛,一個塊對象有時候被稱之為閉包
Block的功能
只有了解了功能茅坛,你才能找到對應(yīng)的場景去使用它。
一個塊是代碼的一個匿名內(nèi)聯(lián)集合-有一個類型參數(shù)列表正如一個函數(shù)则拷,有一個推斷或聲明的返回值類型贡蓖,能在它定義的詞法作用域內(nèi)捕捉狀態(tài),能額外的修改詞法作用域內(nèi)的狀態(tài)煌茬,能在相同的詞法作用域內(nèi)斥铺,可以分享潛在的修改與其他模塊中定義相同的詞法作用域可以繼續(xù)分享和詞法作用域內(nèi)定義的修改狀態(tài)后(堆棧幀)詞法作用域(堆棧幀)已經(jīng)被摧毀了你可以復(fù)制一個街區(qū),甚至將其傳遞給其他線程對延遲執(zhí)行(或者,在它自己的線程,runloop)。編譯器和運行時安排所有變量引用塊保存的所有副本的生活坛善。盡管塊可用純C和c++,一塊也總是一個objective - C對象晾蜘。
block的使用
塊代表通常很小,具有獨立的代碼塊。這樣,他們特別有用的封裝的工作單元可能并發(fā)執(zhí)行,或在項目集合,或者作為回調(diào)當(dāng)另一個操作完成眠屎。塊是一個有用的替代傳統(tǒng)的回調(diào)函數(shù),主要有兩個原因:他們允許你編寫代碼的調(diào)用方法的上下文中執(zhí)行后實現(xiàn)剔交。塊因此經(jīng)常框架方法的參數(shù)改衩。他們允許訪問本地變量岖常。而不是使用回調(diào)函數(shù)需要一個數(shù)據(jù)結(jié)構(gòu),包含了所有你需要的上下文信息來執(zhí)行一個操作,只需直接訪問本地變量。
聲明使用
您還可以創(chuàng)建類型blocks-這樣做所以通常被認(rèn)為是最佳實踐,當(dāng)你使用一塊與給定的簽名在多個地方:例如
typedef float (^MyBlockType)(float, float);
MyBlockType myFirstBlock = // ... ;
MyBlockType mySecondBlock = // ... ;
Block和變量
塊對象的身體內(nèi)的代碼,變量可能被視為五個不同的方法葫督。你可以參考三種標(biāo)準(zhǔn)類型的變量,就像從一個函數(shù):全局變量,包括靜態(tài)局部變量全局函數(shù)(這不是技術(shù)變量)從一個封閉范圍局部變量和參數(shù)塊也支持兩個其他類型的變量:在功能層面上是__block變量竭鞍。這些是可變塊內(nèi)(和封閉范圍)和保存如果任何引用塊復(fù)制到堆。const進口橄镜。最后,在一個方法的實現(xiàn),模塊可能variables-see objective - c實例對象的引用和塊變量偎快。以下規(guī)則適用于變量中使用一塊:訪問全局變量,包括封閉詞法作用域內(nèi)存在的靜態(tài)變量。參數(shù)傳遞給塊訪問(就像參數(shù)函數(shù))蛉鹿。本地堆棧(非靜態(tài))變量封閉詞法作用域為常量變量捕獲滨砍。它們的值是在計劃內(nèi)的塊表達式。在嵌套塊,價值捕獲從最近的封閉范圍妖异。局部變量的封閉詞法作用域聲明__block存儲修改器提供參考,因此是可變的。反映在封閉詞法作用域的任何更改,包括任何其他模塊中定義相同的封閉詞法范圍领追。更詳細地討論這些__block存儲類型他膳。局部變量聲明的詞法作用域內(nèi),局部變量在函數(shù)的完全一樣。每個調(diào)用塊提供了一個新的變量的副本绒窑。這些變量可以作為常量或按引用調(diào)用變量在街區(qū)內(nèi)封閉塊中棕孙。