前言
通過前一篇文章探究block本質,我們已經對block基本上有了一定的瞭解,接下來,我們將對block的一些小細節進行研究
block的變數捕獲
在為了保證block內部能夠正常的訪問外部變數,block有個變數捕獲機制
auto
auto自動變數,離開作用域就會銷燬,在我們定義一個區域性變數的時候,其實都會在這個變數前面預設新增auto,auto會被捕獲到block內部,然後block的內部將會生成一個引數來進行儲存這個變數,而且在捕獲的過程中,是直接將變數的值直接傳遞到這個block中,通過列印,你會發現,在外部修改這個變數,並不會影響到block內部的值
static
使用static的區域性變數也會被捕獲,但是與auto不同的是,static是指標傳遞,直接將自己的地址傳遞給了block內部的引數,既然是指標傳遞,那麼我們在外部修改變數,block內部的引數的值也會跟著改變
auto 與 static之間的差異
auto是值傳遞,static是指標傳遞,兩者之間為什麼會存在差異呢,那是因為自動變數可能會被銷燬,如果一銷燬,那麼block獲取的就有可能是垃圾資料,所以在編譯的時候,block內部就會將自動變數儲存起來。而被static修飾的則是靜態變數,靜態變數並不會被銷燬,所以block內部沒必要去儲存這個變數的值,直接儲存地址就可以了
全域性變數
在程式碼中,全域性變數在哪裡都可以被訪問,既然是所有人都可以訪問,那麼block根本就不需要將全域性變數捕獲到自己的內部
總結
通過上述程式碼,我們可以總結出一些結論
延伸:在一個類的一個物件方法中新增一個block,block是否會捕獲變數
#import "RGPerson.h"
@implementation RGPerson
-(void)test
{
void(^block)(void) = ^{
NSLog(@"%p",self);
};
block();
}
@end
複製程式碼
我們將上述程式碼通過命令列轉換成C++程式碼進行檢視
通過上述兩張圖,我們可以發現self是被捕獲了,但是為什麼會被捕獲呢,答案就在第一張圖中,其實test方法是被預設傳了兩個引數RGPerson * self 和SEL _cmd,既然是引數,那不也就相當於是區域性變數了麼,既然是區域性變數,那麼肯定是能被捕獲的