Object-C高級編程第一篇:Blocks概要

本系列文章主要是對《Objective-C 高級編程》這本書作的讀書筆記總結,除了這本書中的內容之外,也加上了本身對開發技術的理解和一些我的的經驗分享。編程

Blocks是什麼

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

例如:這裏聲明瞭一個名稱爲func的函數指針

int func (int count);

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

int  result = func (10);

若是像下面這樣,使用函數指針來代替直接調用函數,那麼不須要使用函數名也可以使用該函數開發

int  result = (*funcPtr) (10);

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

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

而經過Blocks,源代碼中就可以使用匿名函數。編譯

匿名函數你們已經知道了,那麼如今讓咱們來看一下C語言中可能使用的變量有哪些 :table

  • 局部變量
  • 函數參數
  • 靜態全局變量
  • 靜態局部變量
  • 全局變量

Blocks語法

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

^ 返回值類型 參數列表 表達式讀書筆記

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

如上所示:完整形式的Blocks和C語言的函數定義區別爲:

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

舒適小貼士:由於OS X,iOS 應用程序的源代碼中大量使用Block,因此插入該記號便於查找。

block能夠省略返回類型

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

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

等價於

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

其次,若是不使用參數,block也能夠省略參數列表

語法爲: ^ 表達式

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

Block與C函數對比

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

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

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);

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

截獲局部變量值 是指保存執行block語法瞬間的值,而且保存後就不能修改變量值。

int val = 0;

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

val = 1;

block();

執行上面源代碼,打印val的值爲0。這是由於在block中截獲了局部變量的值,即保存了該變量的瞬間值。因此即便更改了變量的值也不會影響block的打印。

1.4.2__block說明符的使用

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

int val = 0;

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

block();

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

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

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);

源代碼的執行結果爲:val = 1

相關文章
相關標籤/搜索