【OC】块初识
Block簡介
Blocks是C語言的擴充功能。可以用一句話來表示Blocks的擴充功能:帶有自動變量的匿名函數。
匿名函數
所謂匿名函數就是不帶有名稱的函數。C語言的標準不允許存在這樣的函數。例:
int func(int count);它聲明了名稱為func的函數。下面的源代碼中為了調用該函數,必須使用該函數的名稱func。
int result = func(10);但其實使用函數指針也仍需要知道函數名稱。像以下源代碼這樣,在賦值函數指針時,若不使用想復制的函數的名稱,就無法取得該函數的地址。
int (*funcptr)(int) = &func; int result = (*funcptr)(10);而通過Blocks,源代碼中就能夠使用匿名函數。
自動變量
首先回顧一下在C語言的函數中可能使用的變量。
- 自動變量(局部變量)
- 函數的參數
- 靜態變量(靜態局部變量)
- 靜態全局變量
- 全局變量
其中,在函數的多次調用之間能夠傳遞的變量有:
- 靜態變量(靜態局部變量)
- 靜態全局變量
- 全局變量
雖然這些變量的作用域不同,但在整個程序當中,一個變量總保持在一個內存區域。因此,雖然多次調用函數,但改變量值總能保持不變,在任何時候以任何狀態調用,使用的都是同樣的變量值。
int buttonId = 0; void buttonCallblack(int event) {printf("buttonId:%d event=%d\n", buttonId, event); }如果只有一個按鈕,那么該代碼毫無問題,可正常運行。但有多個按鈕時會如何呢?
int buttonId;void buttonCallBack(int event) {printf("buttonId:%d event=%d\n", buttonId, event); }void setButtonCallbacks() {for (int i = 0, i < BUTTON_MAX; ++i) {buttonId = i;setButtonCallback(BUTTON_IDOFFSET + i, &buttonCallback);} }該源代碼到的問題很明顯。全局變量buttonId只有一個,所有回調都使用for循環最后的值。
如果不使用全局變量,回調方會將按鈕的ID作為函數參數傳遞,就能解決該問題。
void buttonCallback(int buttonId, int event) {printf("buttonId:%d event=%d\n", buttonId, event); }但是,回調方在保持回調函數的指針以外,還必須保持回調方的按鈕ID。
C++和Objective-C使用類可保持變量值且能夠多次持有該變量自身。它會聲明持有成員變量的類,由類生成的實例或對象保持該成員變量的值。
我們可以來思考一下剛才例子中用來回調按鈕的類。
@interface ButtonCallbackobject : NSObject {int buttonId_; } @end@implementation ButtonCallbackObject - (id) initWithButtonId:(int)buttonId {self = [super init];buttonId_ = buttonId;return self; }- (void) callback:(int)event {NSLog(@"buttonId:%d event=%d\n", buttonId_, event); } @end如果使用該類,由于對象保持按鈕ID,因此回調方只需要保持對象即可。可如下使用:
void setButtonCallbacks() {for (int I = 0; I < BUTTON+MAX; ++I) {ButtonCallbackObject *callbackObj = [[ButtonCallbackObject alloc] initWithButtonId:I];setButtonCallbackUsingObject(BUTTON_IDOFFSET, callbackObj);} }缺點:增加代碼長度。
Blocks
這時我們就要用到Blocks了。Blocks提供了類似由C++和Objective-C類生成實例或對象來保持變量值的方法,其代碼量與編譯C語言函數差不多。如“帶有自動變量值”,Blocks保持自動變量的值。下面我們使用Blocks實現上面的按鈕回調:
void setButtonCallbacks() {for (int I = 0; I < BUTTON_MAX; ++I) {setButtonCallbackUsingBlock(BUTTON_IDOFFSET + I, ^(int event) {printf("buttonID:%d event=%d\n", I, event);});} }該源代碼將“帶有自動變量i值的匿名函數”設定為按鈕的回調。Blocks中將該匿名函數部分稱為“Block literal”,或簡稱為“Block”。
像這樣,使用Blocks可以不聲明C++和Objective-C類,也沒有使用靜態變量、靜態全局變量或全局變量時的問題。
Block在其他程序語言中的名稱
總結
- 上一篇: 【Word标题样式随正文的样式进行首行缩
- 下一篇: pv添加入vG和VG中删除pv