標籤:style io ar os 使用 sp on 資料 log
Block實體形式如下:^(傳入參數列){行為主體};
Block實體開頭是“^”,接著是由小括弧所包起來的參數列(比如 int a, int b, int c),行為主體由大括弧包起來,專有名字叫做block literal。行為主體可以用return回傳值,類型會被compiler自動辨別。如果沒有參數列要寫成: ^(void)。
ps:一個block雖然和函數指標有些相似,但是實際上代表一個底層資料結構,類似與對象,有編譯器去建立和管理。block的一個優勢是可以使用其自己範圍外的變數,例如,一個block可以讀取其父範圍的變數值,此值是copy到了block heap的資料結構中。當block被加入到dispatch queue中,這些值通常為唯讀形式。block的聲明和函數指標類似,只是把*改為了^,我們可以傳遞參數給block,也可以接收其返回的值。
block存取變數
1、可以讀取和Block pointer同一個Scope的變數值:
下面來看一段很有意思的代碼:
{
int outA = 8;
int (^myPtr)(int) = ^(int a){ return outA + a;}; //block裡面可以讀取同一類型的outA的值
outA = 5; //在調用myPtr之前改變outA的值
int result = myPtr(3); // result的值仍然是11,並不是8
NSLog(@"result=%d", result);
}
為什麼result 的值仍然是11?而不是8呢?事實上,myPtr在其主體中用到的outA這個變數值的時候做了一個copy的動作,把outA的值copy下來。所以,之後outA即使換成了新的值,對於myPtr裡面copy的值是沒有影響的。
需要注意的是,這裡copy的值是變數的值,如果它是一個記憶體的位置(地址),換句話說,就是這個變數是個指標的話,
它的值是可以在block裡被改變的。如下例子:
{
NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil];
int result = ^(int a){[mutableArray removeLastObject]; return a*a;}(5);
NSLog(@"test array :%@", mutableArray);
}
原本mutableArray的值是{@"one",@"two",@"three"},在block裡面被更改mutableArray後,就變成{@"one", @"two"}了。
2、直接存取static類型的變數
{
static int outA = 8;
int (^myPtr)(int) = ^(int a){ outA = 5; return outA + a;};
int result = myPtr(3); //result的值是8,因為outA是static類型的變數
NSLog(@"result=%d", result);
}
3、Block Variable類型的變數
在某個變數前面如果加上修飾字“__block”的話(注意,block前面有兩個底線),這個變數就稱作block variable。那麼在block裡面就可以任意修改此變數的值,如下代碼:
{
__block int num = 5;
int (^myPtr)(int) = ^(int a){return num++;};
int (^myPtr2)(int) = ^(int a){return num++;};
int result = myPtr(0); //result的值為5,num的值為6
result = myPtr2(0); //result的值為6,num的值為7
NSLog(@"result=%d", result);
}
iOS block的一些理解