block簡介:
block的實際行為和function很像,最大的差別是在可以訪問同乙個scope的變數值。block實體形式如下:
^(傳入引數列);
block實體開頭是「^」,接著是由小括號所包起來的引數列(比如 int a, int b, int c),行為主體由大括號包起來,專有名字叫做block literal。行為主體可以用return回傳值,型別會被compiler自動辨別。如果沒有引數列要寫成: ^(void)。
例如下面的乙個例子:
[cpp]view plain
copy
^(int
a);
這是代表block會回傳輸入值的平方值(
int a
就是引數列
,return a*a;
就是行為主體
)。記得行為主體裡最後要加「;」,因為是敘述,而整個{}最後也要加「;」,因為block是物件實體。用法如下:
[cpp]view plain
copy
intresult = ^(
inta)(5);
nslog(@"%d"
, result);
很奇怪吧?後面的小括號裡面的5會被當成a的輸入值,然後經由block輸出 5*5 = 25指定給result這個變數。
有沒有簡單一點的方法嗯?不然每次都寫這麼長?有。接下來介紹乙個叫做block pointer的東西來簡化我們的寫法。
block pointer是這樣定義的:
回傳值(^名字)(引數列);
比如下面的例子:
[cpp]view plain
copy
//宣告乙個square的block pointer,其所指向的block有乙個int輸入和int輸出
int(^square)(
int);
//將block實體指定給square
square = ^(int
a);
//呼叫方法,感覺是是不是很像function的用法?
intresult = square(5);
nslog(@"%d"
, result);
是不是變的簡單了?
也可以吧block pointer當成引數傳遞給乙個function,比如:
[cpp]view plain
copy
void
myfunction(
int(^mysquare)(
int));
//function的定義,將block作為引數
int(^mysquare)(
int) = ^(
inta);
//定義乙個mysquare的block pointer變數
myfunction(mysquare); //把mysquare作為myfunction的引數
上面的三行**其實等價於下面這行**:
[cpp]view plain
copy
myfunction( ^
int(
inta) );
當其作為object-c method的傳入值的話,需要把型別寫在變數前面,然後加上小括號。比如下面這種寫法:
[cpp]view plain
copy
-(void
)objcmethod:(
int(^)(
int))square;
//square引數的型別是int(^)(int)
訪問變數
1、可以讀取和block pointer同乙個scope的變數值:
[cpp]view plain
copy
; //block裡面可以讀取同一型別的outa的值
intresult = myptr(3);
// result is 11
nslog(@"result=%d"
, result);
}
下面來看一段很有意思的**:
[cpp]view plain
copy
; //block裡面可以讀取同一型別的outa的值
outa = 5; //在呼叫myptr之前改變outa的值
intresult = myptr(3);
// result的值仍然是11,並不是8
nslog(@"result=%d"
, result);
}
為什麼result 的值仍然是11?而不是8呢?事實上,myptr在其主體中用到的outa這個變數值的時候做了乙個copy
的動作,把outa的值copy下來。所以,之後outa即
使換成了新的值,對於myptr裡面copy的值是沒有影響的。
需要注意的是,這裡copy的值是變數的值,如果它是乙個記憶體的位置(位址),換句話說,就是這個變數是個指標的話,
它的值是可以在block裡被改變的。如下例子:
[cpp]view plain
copy
(5);
nslog(@"test array :%@"
, mutablearray);
}
原本mutablearray的值是,在block裡面被更改mutablearray後,就變成了。
2、直接訪問static型別的變數
[cpp]view plain
copy
; outa = 5;
intresult = myptr(3);
//result的值是8,因為outa是static型別的變數
nslog(@"result=%d"
, result);
}
甚至可以直接在block裡面修改outa的值,例如下面的寫法:
[cpp]view plain
copy
; int
result = myptr(3);
//result的值是8,因為outa是static型別的變數
nslog(@"result=%d"
, result);
}
3、block variable型別的變數
在某個變數前面如果加上修飾字「_
_block」的話(注意,block前面有兩個下劃線),這個變數就稱作block variable。
那麼在block裡面就可以任意修改此變數的值,如下**:
[cpp]view plain
copy
; int
(^myptr2)(
int) = ^(
inta);
intresult = myptr(0);
//result的值為5,num的值為6
result = myptr2(0); //result的值為6,num的值為7
nslog(@"result=%d"
, result);
}
因為myptr和myptr2都有用到num這個block variable,最終num的值為7.
IOS中 Block簡介與用法(一)
block簡介 block的實際行為和function很像,最大的差別是在可以訪問同乙個scope的變數值。block實體形式如下 傳入引數列 block實體開頭是 接著是由小括號所包起來的引數列 比如 int a,int b,int c 行為主體由大括號包起來,專有名字叫做block litera...
IOS中 Block簡介與用法(一)
block簡介 block的實際行為和function很像,最大的差別是在可以訪問同乙個scope的變數值。block實體形式如下 傳入引數列 block實體開頭是 接著是由小括號所包起來的引數列 比如 int a,int b,int c 行為主體由大括號包起來,專有名字叫做block litera...
IOS中 Block簡介與用法(一)
block簡介 block的實際行為和function很像,最大的差別是在可以訪問同乙個scope的變數值。block實體形式如下 傳入引數列 block實體開頭是 接著是由小括號所包起來的引數列 比如 int a,int b,int c 行為主體由大括號包起來,專有名字叫做block litera...