默認情況下耍属,在block中訪問的外部變量是復制過去的撬槽,即:寫操作不對原變量生效。但是你可以加上 __block 來讓其寫操作生效茫虽,示例代碼如下:
__block int a = 0;
void (^foo)(void) = ^{
a = 1;
};
foo();
//這里,a的值被修改為1
為什么寫操作就生效了既们?
我們都知道:Block不允許修改外部變量的值席噩,這里所說的外部變量的值,指的是棧中指針的內(nèi)存地址贤壁。__block 所起到的作用就是只要觀察到該變量被 block 所持有悼枢,就將“外部變量”在棧中的內(nèi)存地址放到了堆中。進而在block內(nèi)部也可以修改外部變量的值脾拆。
Block不允許修改外部變量的值馒索。Apple這樣設計,應該是考慮到了block的特殊性名船,block也屬于“函數(shù)”的范疇绰上,變量進入block,實際就是已經(jīng)改變了作用域渠驼。在幾個作用域之間進行切換時蜈块,如果不加上這樣的限制,變量的可維護性將大大降低迷扇。又比如我想在block內(nèi)聲明了一個與外部同名的變量百揭,此時是允許呢還是不允許呢?只有加上了這樣的限制蜓席,這樣的情景才能實現(xiàn)器一。于是棧區(qū)變成了紅燈區(qū),堆區(qū)變成了綠燈區(qū)厨内。
__block int a = 0;
NSLog(@"定義前:%p", &a); //棧區(qū)
void (^foo)(void) = ^{
a = 1;
NSLog(@"block內(nèi)部:%p", &a); //堆區(qū)
};
NSLog(@"定義后:%p", &a); //堆區(qū)
foo();
2016-05-17 02:03:33.559 LeanCloudChatKit-iOS[1505:713679] 定義前:0x16fda86f8
2016-05-17 02:03:33.559 LeanCloudChatKit-iOS[1505:713679] 定義后:0x155b22fc8
2016-05-17 02:03:33.559 LeanCloudChatKit-iOS[1505:713679] block內(nèi)部: 0x155b22fc8