《Objective-C 高級編程》第一篇:Block概要

本系列文章主要是對《Objective-C 高級編程》這本書做的讀書筆記總結,除了這本書中的內容以外,也加上了自己對開發(fā)技術的理解和一些個人的經驗分享。

一、什么是Blocks

1.1 Blocks概要

Blocks是C語言的擴充功能,是帶有局部變量的匿名函數(匿名其實就是沒有名稱的函數,C語言標準不允許匿名函數)

例如:這里聲明了一個名稱為func的函數

int func (int count);

為了調用該函數,必須使用該函數的名稱

int  result = func (10);

如果像下面這樣,使用函數指針來代替直接調用函數,那么不需要使用函數名也能夠使用該函數

int  result = (*funcPtr) (10);

但其實使用函數指針也仍然需要知道函數名稱。例如以下,在賦值給函數指針時,若不使用函數的名稱,就取法取得該函數的地址。

int (*funcPtr)(int) = &func;
int  result = (*funcPtr) (10);

而通過Blocks,源代碼中就能夠使用匿名函數。

匿名函數大家已經知道了,那么現在讓我們來看一下C語言中可能使用的變量有哪些 :

  • 局部變量
  • 函數參數
  • 靜態(tài)全局變量
  • 靜態(tài)局部變量
  • 全局變量

1.2 Blocks語法

下面我們來詳細講解一下帶有局部變量值的匿名函數Blocks的語法:

^ 返回值類型 參數列表 表達式

以下定義表明這是一個表示沒有返回類型,并且參數為int型的Block
^ void (int a, int b) {
  // do sth
}

如上所示:完整形式的Blocks和C語言的函數定義區(qū)別為:

  • 沒有函數名 (匿名函數)
  • 沒有 ^

溫馨小貼士:因為OS X,iOS 應用程序的源代碼中大量使用Block,所以插入該記號便于查找。

block可以省略返回類型

省略返回類型的語法為: ^ 參數列表 表達式

^ void (int a, int b) {表達式}

等價于

^ (int a, int b) {表達式}

其次,如果不使用參數,block也可以省略參數列表

語法為: ^ 表達式

^ {
  // 說點什么吧,少年
}

1.3 Block與C函數對比

int func (int count) 
{
  return count + 1;
}
// 函數func的地址賦值給函數指針變量funcPtr
// 在block語法下可將block賦值給聲明為block類型的變量
int (*funcPtr) (int) = &func
int (^blockName) (int)

與前面的使用函數指針的源代碼對比可知,聲明block類型變量僅僅是將聲明函數指針類型變量 * 變?yōu)?^

int (^block) (int) = ^ (int count) {
    return count + 1;
}

block類型變量與c語言變量相同,block也可以作為函數參數傳遞或者函數的返回值

  • 作為函數參數
void func ( int (^block) (int) ) {
  //
}
  • 作為函數的返回值
int (^func()) (int) {
  //
  return ^ (int count) {
      return count + 1;
  };
}

由上面源代碼可以看出在使用block變量時,記錄方式非常復雜。我們可以像使用函數指針類型那樣,使用 typedef來解決

  typedef int (block_t) (int)

我們來對比以下

// 沒有定義前
void func ( int (^block) (int) ) {

}

// 定義后
void func (block_t block) {

}

另外,Block調用 和 C語言中使用函數指針調用函數的方法幾乎完全相同。

int result = (*funcPtr)(10);
int result = block(10);

也可以使用指向block類型變量的指針調用block

typedef int (^block_t) (int)

block_t block = ^ (int count) {
  return count + 1;
}

block_t *blockPtr = █

(* blockPtr)(10);

1.4 截獲局部變量值以及__block說明符的使用

1.4.1 截獲局部變量值

截獲局部變量值是指保存執(zhí)行block語法瞬間的值,并且保存后就不能修改變量值。

int val = 0;

void (^block) (void) = ^ {
  NSLog(@"val = %d", val);
}

val = 1;

block();

執(zhí)行上面源代碼,打印val的值為0。這是因為在block中截獲了局部變量的值,即保存了該變量的瞬間值。所以即使更改了變量的值也不會影響block的打印。

1.4.2__block說明符的使用

執(zhí)行下面源代碼,會產生編譯錯誤。

int val = 0;

void (^block) (void) = ^ {
  val = 1;
}

block();

NSLog(@"val = %d", val);

向截獲的變量直接賦值會發(fā)生編譯錯誤,但使用截獲的值卻不會報錯。

id array = [NSMutableArray array];

void (^block) (void) = ^ {
  id obj = [[NSObject alloc] init];
  [array addObject:obj];
}

block();

若想在block中修改局部變量的值,需要在該自動變量前加 __block 說明符。

__block int val = 0;

void (^block) (void) = ^ {
  val = 1;
}

block();

NSLog(@"val = %d", val);

源代碼的執(zhí)行結果為:val = 1

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 轉至元數據結尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉至元數據起始第一章:isa和Class一....
    40c0490e5268閱讀 2,032評論 0 9
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發(fā)現,斷路器,智...
    卡卡羅2017閱讀 136,506評論 19 139
  • 當年流行的美劇CSI邁阿密第10季里,前瞻性的出現過一款透明手機,在劇中與會拐彎的子彈一起成了觀眾的怨念。在CW臺...
    2平方單人床閱讀 661評論 0 0
  • 創(chuàng)業(yè)公司不需要產品經理 近期幫朋友公司管理整體公司,又接觸了一線的產品技術、市場、商務等等,讓我不禁想寫點東西,分...
    舒星閱讀 924評論 0 18
  • 總是把開頭想得那么難 把過程想得那么簡單 卻沒想到結局那么悲慘 時間在六月的熾陽下翻滾掙扎 蟬鳴著一聲兩聲是要離開...
    不邇閱讀 489評論 0 1

友情鏈接更多精彩內容