【OC】块初识
Block簡介
Blocks是C語言的擴充功能。可以用一句話來表示Blocks的擴充功能:帶有自動變量的匿名函數(shù)。
匿名函數(shù)
所謂匿名函數(shù)就是不帶有名稱的函數(shù)。C語言的標準不允許存在這樣的函數(shù)。例:
int func(int count);它聲明了名稱為func的函數(shù)。下面的源代碼中為了調(diào)用該函數(shù),必須使用該函數(shù)的名稱func。
int result = func(10);但其實使用函數(shù)指針也仍需要知道函數(shù)名稱。像以下源代碼這樣,在賦值函數(shù)指針時,若不使用想復(fù)制的函數(shù)的名稱,就無法取得該函數(shù)的地址。
int (*funcptr)(int) = &func; int result = (*funcptr)(10);而通過Blocks,源代碼中就能夠使用匿名函數(shù)。
自動變量
首先回顧一下在C語言的函數(shù)中可能使用的變量。
- 自動變量(局部變量)
- 函數(shù)的參數(shù)
- 靜態(tài)變量(靜態(tài)局部變量)
- 靜態(tài)全局變量
- 全局變量
其中,在函數(shù)的多次調(diào)用之間能夠傳遞的變量有:
- 靜態(tài)變量(靜態(tài)局部變量)
- 靜態(tài)全局變量
- 全局變量
雖然這些變量的作用域不同,但在整個程序當中,一個變量總保持在一個內(nèi)存區(qū)域。因此,雖然多次調(diào)用函數(shù),但改變量值總能保持不變,在任何時候以任何狀態(tài)調(diào)用,使用的都是同樣的變量值。
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只有一個,所有回調(diào)都使用for循環(huán)最后的值。
如果不使用全局變量,回調(diào)方會將按鈕的ID作為函數(shù)參數(shù)傳遞,就能解決該問題。
void buttonCallback(int buttonId, int event) {printf("buttonId:%d event=%d\n", buttonId, event); }但是,回調(diào)方在保持回調(diào)函數(shù)的指針以外,還必須保持回調(diào)方的按鈕ID。
C++和Objective-C使用類可保持變量值且能夠多次持有該變量自身。它會聲明持有成員變量的類,由類生成的實例或?qū)ο蟊3衷摮蓡T變量的值。
我們可以來思考一下剛才例子中用來回調(diào)按鈕的類。
@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,因此回調(diào)方只需要保持對象即可??扇缦率褂?#xff1a;
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類生成實例或?qū)ο髞肀3肿兞恐档姆椒?#xff0c;其代碼量與編譯C語言函數(shù)差不多。如“帶有自動變量值”,Blocks保持自動變量的值。下面我們使用Blocks實現(xiàn)上面的按鈕回調(diào):
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值的匿名函數(shù)”設(shè)定為按鈕的回調(diào)。Blocks中將該匿名函數(shù)部分稱為“Block literal”,或簡稱為“Block”。
像這樣,使用Blocks可以不聲明C++和Objective-C類,也沒有使用靜態(tài)變量、靜態(tài)全局變量或全局變量時的問題。
Block在其他程序語言中的名稱
總結(jié)
- 上一篇: 【Word标题样式随正文的样式进行首行缩
- 下一篇: pv添加入vG和VG中删除pv