OC高階特性 Block匿名函式

2021-07-03 15:47:17 字數 2988 閱讀 5225

塊是objective-c語言提供的乙個強大特性,博主會介紹塊語法的意義、塊記憶體管理、怎樣在程式中開發塊和怎樣使用現有api(如foundation框架)中的塊。

簡言之,塊提供了一種方式,使用這種方式可以建立一組語句(即**塊)並將這些語句賦予乙個變數,隨後就可以呼叫這個變數。從這方面看,塊與函式方法類似,但除了是可執行**外,塊還含有與堆記憶體和棧記憶體繫結的變數。塊就是乙個實現的閉包(closure),乙個允許訪問其常規範圍之外變數的函式。此外,乙個objective-c塊實際上就是乙個物件;乙個nsobject類的子類,擁有nsobject類的所有相關屬性(如可以向塊傳送訊息)。

在學習使用塊編寫的過程中,難點之一是掌握塊的語法。本段內容詳解介紹塊語法,並且會通過示例展示塊在**中的作用。

塊型別由返回值型別和引數型別列表構成。使用脫字元(^)可以宣告塊型別的變數。

函式宣告

函式宣告:int

sum(int a, int b);

函式型別int(int, int);

函式指標型別:int(*)(int, int);

將函式指標型別重新命名:typedef int(*funp)(int, int);

宣告注意:這裡只要將函式指標型別標誌"*"改為block語法的標誌"^"就是block語法。

int (^sum)(int, int)

上面博主已經介紹過了,block是將乙個函式的實現賦予block變數,下面定義函式。

//3.函式定義語法

intsum(int a, int b)

定義把前面的block變數型別拿過來

int (^sum)(int, int)

將函式的定義賦給block變數sum

int (^sum)(int, int) = ^int (int a, int b)

注意:

1.後面的函式實現的名字被去掉了,這裡賦給block變數的其實是乙個匿名函式。

2.等號右面加了乙個block語法標誌」^」不能省略。

這樣乙個block語法塊、或者叫做匿名函式就建立好了

1.塊常量表示式—-沒有設定返回值型別的塊常量表示式

^int (int addend)
無需再塊定義中為這個塊設定返回值型別,因為編譯器會從塊主題中的return語句推斷出返回值的資料型別。

2.不帶引數的塊常量定義

^
塊語法元素的比較

塊語法元素

塊變數宣告

塊常量表示式

脫字元標識乙個塊變數宣告的開始。脫字元位於變數名稱之前,兩者都被封裝在圓括號中

標識乙個塊變數表示式的開始

名稱塊變數的名稱是必選項

塊常量表示式沒有名稱

返回值型別

在塊變數宣告中返回值型別是必選項。沒有返回值的塊變數會將返回值宣告為void

從塊表示式的語句主題推斷出返回值型別。如果塊表示式的語句主題中有乙個以上的return語句,那麼他們的返回值必須為同一類

引數在塊變數宣告中,引數型別列表是必選項。如果塊變數沒有引數,必須將引數型別列表宣告為void

在塊常量表示式中,引數列表是可選項

如前面所述,塊就是乙個實現的閉包,就是乙個允許訪問在其常規範圍外部宣告的區域性變數的函式。為了理解這些概念,讓我們先來了解範圍和可見性規則。變數的可見性是指變數在程式的哪個(些)部分中可以被訪問,這也稱為變數的範圍。例如,在c語言函式定義中宣告的變數擁有區域性範圍,這意味著這些變數僅僅在該函式中是可見的和可訪問的(注意,函式還可以引用全域性變數)。與c語言函式相比,塊引數通過以下特性提高了變數的可見性。

塊的一大特性就是支援詞彙範圍。與之相反,c語言函式無法訪問在其定義外部宣告的區域性變數。

void logvalue() 

int main(int argc, const

char *argv)

塊支援詞彙範圍,因此塊常量表示式可以訪問在同一詞彙範圍內宣告的變數。此外,一方面,能夠定義變數的地方就能夠定義塊,例如,在函式、方法和其他塊中都可以定義塊。另一方面、c語言函式無法在其他函式和方法中定義。以下**可以成功編譯和執行,因為變數myvar是在logvalueblock塊所在的詞彙範圍內宣告的。

;

logvalueblock();

}

如以上**所示,乙個塊訪問了在其定義之外宣告的區域性變數。尤其是,這些區域性變數是在宣告塊常量表示式之前,在乙個封閉範圍內被宣告(和初始化)的。可以用花括號劃定區域性範圍,此外,還可以巢狀捍衛。一方面,如上面**所示,變數myvar是定義logvalueblock塊的範圍內被宣告的,而且其宣告位於塊常量表示式之前,因為可以在這個塊常量表示式中使用。另一方面,如果區域性變數myvar是在塊常量表示式之後宣告和初始化的,則塊對區域性變數的訪問是非法的。

;

logvalueblock();

}

預設情況下,在塊常量表示式中通過詞彙範圍訪問的塊區域性變數不能修改。使用儲存型別修改符__block可以將這些變數切換為讀寫模式(可以修改)。除了c語言的變長陣列(不是由常量表示式表示長度的陣列)和含有變長陣列的c語言結構之外,可以對objective-c支援的所有型別使用__block修改符。__block修改符不能與區域性變數儲存修改符auto、register和static組合使用。

__block int myvar = 10;

void(^incblock)(int) = ^(int amount) ;

incblock(5);

當引用變數的塊被賦值到堆儲存區域時,使用__block修飾符的變數也會被複製到堆儲存區域。這個本部落格最後的知識點因除了記憶體管理的話題,下面將介紹該內容。

高階函式和匿名函式

1.高階函式 高階函式就是把函式當成引數傳遞的函式。例如 def add x,y,f return f x f y print add 4,3,abs 結果是 7 map 函式 map 函式的python內建的高階函式,他接受乙個函式f 和引數list,並把list的元素傳遞給函式f,然後返回乙個函...

Python高階函式 匿名函式

當我們在傳入函式時,有些時候,不需要顯示定義函式,直接傳入匿名函式更方便。在python中,對匿名函式提供了有限支援。還是以map 函式為例,計算f x x 2時,除了定義乙個f x 的函式外,還可以直接傳入匿名函式 list map lambda x x x,1,1,2,3,4,5,6,7,8,9...

Python 函式高階 匿名函式

不需要使用def去定義,也不用給函式取名字,用lambda表示式來定義,這種函式叫做匿名函式 lambda 引數 表示式 作為返回值 將以下函式改為匿名函式 普通函式 def func var1 return var1 2 匿名函式寫法 lambda var1 var1 2 匿名函式定義後可以直接呼...