- 寫在前面: 翻翻各個(gè)iOS大牛的博客,或者在他們回答新手如何學(xué)習(xí)iOS開發(fā)時(shí),"多看,一定要看蘋果官方文檔"這句話100%會(huì)出現(xiàn)."蘋果人家是權(quán)威,多少博客都是翻譯一遍罷了""不要啃人家嚼過的甘蔗".理都懂,然并卵.就結(jié)合自己情況來說,之前也看的不多原因有三:
- 1.中文看著多舒服,人忙忙的,問題解決就ok,想那多干啥
- 2.臥槽,密密麻麻這是啥,看兩行嚇得我電腦都關(guān)上了
- 3.問問自己的定位,你是不是一位合格并且有上進(jìn)心的開發(fā)者?
其實(shí)對于大多數(shù)開發(fā)者來說,入了門之后,耳濡目染的都會(huì)寫,認(rèn)識(shí)些英文,所以其實(shí)還是一個(gè)懶,這句話也在說自己. 時(shí)光恍恍惚惚時(shí)間就這么沒了,maybe失去些東西會(huì)讓人突然安靜下來.學(xué)習(xí)iOS一直自己做筆記,翻了翻自己的筆記,有些概念模模糊糊模棱兩可,覺得是時(shí)候總結(jié)一波了.不想做咸魚的我也就在這時(shí)候靜下心來,看了一晚上蘋果官網(wǎng)文檔,對,是一晚上.不會(huì)的單詞右擊Look up, 復(fù)雜些的google.很惡心自己英文下降很多,但是觀后感是:臥槽,這玩意才是武功秘籍好伐, 不管是guide還是一些api說明,實(shí)例code,絕逼權(quán)威,個(gè)人也覺得不會(huì)比一些中博客"翻譯"過來的難理解. 一晚上,"soga...原來是這樣!""這個(gè)這么理解才對""媽蛋,吃了這么久的二手甘蔗",是我整個(gè)心理活動(dòng).
當(dāng)然夸張了, 只是覺得一是靜下心來認(rèn)真那種感覺很難得,二是官方文檔真的很好.
這個(gè)集我想著自己盡量多的總結(jié)下官方文檔的原文內(nèi)容(不會(huì)大段落的翻譯),帶著自己(如果能幫到你就更好啦), 咱們?nèi)コ砸皇重?!
英文全部來自官方文檔iOS9.1Document ,如果有錯(cuò)誤,可能是復(fù)制或者打字錯(cuò)誤, 開局了:
- Blocks Can Capture Values from the Enclosing Scope
(先別急著翻譯,看下下面的這兩個(gè)方法,猜下輸出先.)
As well as containing executable code, a block also has the ability to capture state from its enclosing scope.
If you declare a block literal from within a method, for example, it’s possible to capture any of the values accessible within the scope of that method, like this:
- (void)testMethod {
int anInteger = 42;
void (^testBlock)(void) = ^{
NSLog(@"Integer is: %i", anInteger);
};
testBlock();
}
In this example, anInteger is declared outside of the block, but the value is captured when the block is defined.
Only the value is captured, unless you specify otherwise. This means that if you change the external value of the variable between the time you define the block and the time it’s invoked, like this:
int anInteger = 42;
void (^testBlock)(void) = ^{
NSLog(@"Integer is: %i", anInteger);
};
anInteger = 84;
testBlock();
the value captured by the block is unaffected. This means that the log output would still show:
Integer is: 42 //輸出是42```
It also means that the block cannot change the value of the original variable, or even the captured value (it’s captured as a const variable).
```objc
這里來總結(jié)文檔意思: 不僅可以包含可執(zhí)行代碼一樣,block能力超群,可以從封閉范圍內(nèi)獲取值.
其實(shí)道理很簡單,答案應(yīng)該有2種: 42 ,84
42是覺得,可以的,不過這里是值傳遞
84覺得,外面修改了,我里面也用了,有可能吧.
隨后文檔給了解釋: 除非你特殊定義,不然這個(gè)局部變量存在Block中后,后面你修改,它內(nèi)部value是不影響的.
就像const來修飾一個(gè)變量,讓它只讀!
問題來了,那么怎樣叫特殊定義,怎樣可以修改? 來接下來就有解釋了.
- Use __block Variables to Share Storage(這個(gè)標(biāo)題自己翻譯下)
If you need to be able to change the value of a captured variable from within a block, you can use the __block storage type modifier on the original variable declaration. This means that the variable lives in storage that is shared between the lexical scope of the original variable and any blocks declared within that scope.
As an example, you might rewrite the previous example like this:
__block int anInteger = 42;
void (^testBlock)(void) = ^{
NSLog(@"Integer is: %i", anInteger);
};
anInteger = 84;
testBlock();
Because anInteger is declared as a __block variable, its storage is shared with the block declaration. This means that the log output would now show:
Integer is: 84 //這里輸出就成84了
也就是說,用__block修飾變量,外部修改了這個(gè)變量,那么block里用得時(shí)候,就得注意了,值就變了.
用歪果仁的原文就是,Because anInteger is declared as a __block variable,
its storage is shared with the block declaration,分享給了你,這思維咋翻譯嘛....
也就可以理解為,指針傳遞,帶了__block這個(gè)修飾變量,外面修改,里面也會(huì)改
It also means that the block can modify the original value, like this:
(在看看這個(gè):)
__block int anInteger = 42;
void (^testBlock)(void) = ^{
NSLog(@"Integer is: %i", anInteger);
anInteger = 100;
};
testBlock();
NSLog(@"Value of original variable is now: %i", anInteger);
This time, the output would show:
輸出分別是:
Integer is: 42
Value of original variable is now: 100
- 也就意味者,外部修改變量,會(huì)影響block調(diào)用時(shí)它的值,同時(shí)block內(nèi)部也可以修改,有執(zhí)行順序,猜猜那么下段怎么輸出.
- (void)text {
__block int a = 10;
void(^block)() = ^void() {
a = 20; //先修改a
NSLog(@"a = %d",a);
};
block();
NSLog(@" new a = %d",a);
}
//沒錯(cuò),內(nèi)部是按順序執(zhí)行的, a = 20 ,new a = 20
- 我也很疑惑,為什么加上_ block就可以了,是不是變量作用域的問題. 那么我就不加 _block,而是把a(bǔ)修飾成全局的試試? 加上static是什么效果? 自己去試試吧,下面是結(jié)果.
int a = 10;
- (void)text {
void(^block)() = ^void() {
a = 30;
NSLog(@"%d",a);
};
a = 20;
block();
NSLog(@" new a = %d",a);
/* 輸出a = 30; new a = 30; 所以執(zhí)行順序就明白了:
先到a = 20; 然后進(jìn)block
*/
--------------------------------------------
- (void)text2 {
static int a = 5;
void(^block)() = ^void() {
NSLog(@"%d",a);
};
a = 20;
block();
NSLog(@" new a = %d",a);
/* 輸出a = 20; new a = 20; 所以執(zhí)行順序就明白了:
先到a = 20; 然后進(jìn)block
*/
------------------------------
- (void)text3 {
static int a = 5;
void(^block)() = ^void() {
a = 30;
NSLog(@"%d",a);
};
a = 20;
block();
NSLog(@" new a = %d",a);
//輸出 a = 30; new a = 30;
}
所以蘋果這里說__block的意義在于,1. 在一個(gè)函數(shù)中,它不僅可以保存代碼塊
更是可以跳出那個(gè){},獲取外面的值 2.加上__block后,更是在block塊兒內(nèi)獲取外面值得時(shí)候,先修改,再存入,
同時(shí)block內(nèi)可以修改這個(gè)變量值,這里思想就不會(huì)禁錮在變量的作用域上.而是說Block的特性
所以不糾結(jié)其他的,總結(jié)block下就是兩種傳遞:
1.值傳遞
2.指針傳遞. 為啥這么叫,用clang再編譯下,然后查找對應(yīng)傳遞,就會(huì)明白啦!