Block
使用^來聲明一個block變量
void (^printBlock)(NSString *x);
printBlock =^(NSString *str){
NSLog(@"print:%@",str);
};
返回值 ^block名 形參 {塊內容}
概述
- 在很多情況下,并不需要將block聲明一個變量,在需要使用block的地方直接用內嵌的方式將block的內容寫出來
- 一般來說block只能讀取在同一個作用于的變量而沒有辦法修改在block外定義的任何變量,此時若我們想這些變量能在block中被修改,就必須使用
__block
修飾詞。如下,有修飾詞的變量可寫,沒有__block修飾的變量只讀-
__block
不能修飾長度為不定值的變量
-
__block int NBNum = 1;
int notNBNum = 0;
void (^doSomeThing)(int n);
doSomeThing = ^(int n){
NBNum++;
NSLog(@"%d",NBNum);
NSLog(@"%d",notNBNum)
};
功能
Block是一種具有匿名功能的內嵌函數,
-
它的特性如下:
- 形參
- 有返回值
- lexical scope(作用域)
它的使用時機:表示,簡化一段代碼,特別適合用于封裝一些小型的task或者作為一個工作完成的callback
-
它的優點(相對于
delegate
和callback
):- 可以直接在block中直接寫入等下要執行的代碼,直接將代碼變成函數的參數傳入函數中,這是block最常使用的地方
- 可以存儲局部變量,傳統的callback讀寫局部變量需要把數據封裝成一個結構體,而block可以直接存取
-
引用計數
- 如果在blcok中引用了OC對象,那么引用計數+1;__block對引用計數無影響
-
使用注意
- 避免在if for循環等局部定義域內定義block并在其外面引用
Block的本質
當你定義完block之后,其實是創建了一個函數,在創建結構體的時候把函數的指針一起傳給了block,所以之后可以拿出來調用
__block修飾的變量傳入Blcok是地址傳遞,普通變量傳入block是值傳遞
Block的三種狀態:
_NSConcreteGlobalBlock
全局靜態;_NSConcreteStackBlock
棧保存,函數作用域外銷毀;_NSConcreteMallocBlock
堆保存,retain == 0銷毀