定義
帶有局部變量(自動變量)的匿名函數(shù)
ps :
“帶有局部變量”:可以獲取到塊外面的變量(將變量放在自身(block)的結(jié)構(gòu)體中豌拙;獲取的只是改變量的瞬時值抓谴,后面對變量的修改不會使塊中的變量也被修改)讹语,但是只能讀攘骺弧嘶摊;
要改寫的話需給變量前面加"__block"修飾符 _(將該變量變成和Block一樣的結(jié)構(gòu)體實例,并在自身的結(jié)構(gòu)體添加一個對結(jié)構(gòu)體中值的指針引用伏社;分開兩個結(jié)構(gòu)體(block的結(jié)構(gòu)體 , 變量的結(jié)構(gòu)體)是為了能夠在多個Block中用到_block變量)
本質(zhì)
C語言中的結(jié)構(gòu)體和函數(shù)抠刺,OC語言中對象
語法
^ 返回值類型 參數(shù)列表 表達式(斜體代表可省略)
ps:
省略返回值類型時,如果表達式中有return就使用該返回值的類型摘昌,如果沒有return就使用void類型;表達式中含多個return語句時速妖,所有return的返回值類型必須一致
分類
所屬類 | 說明 | |
---|---|---|
棧塊 | _NSConcreteStackBlock | 編譯器會給每個塊分配好棧內(nèi)存, 然而等離開了相應(yīng)的范圍之后聪黎,編譯器有可能把分配給塊的內(nèi)存覆寫掉罕容。 |
堆塊 | _NSConcreteMallocBlock | 帶引用計數(shù)的塊對象;棧塊通過copy方法可成為堆塊 |
全局塊 | _NSConcreteGlobalBlock (存儲域為程序的數(shù)據(jù)區(qū)域 .data區(qū)) | 塊不會捕捉任何狀態(tài)(比如外圍的變量等),運行時也無須有狀態(tài)來參與杀赢。塊所使用的整個內(nèi)存區(qū)域烘跺,在編譯期已經(jīng)完全確定了。 |
ps:全局塊:對其的拷貝操作是個空操作脂崔,因為全局塊決不可能為系統(tǒng)所目收滤淳。這種塊實際上相當(dāng)于單例。下面就是個全局塊:
void (^ablock)() = ^{
NSLog(@"This is a block");
}
由于運行該塊所需的全部信息都能在編譯期確定砌左,所以可把它做成全局塊脖咐。這完全是種優(yōu)化技術(shù):若把如此簡單的塊當(dāng)成復(fù)雜的塊來處理,那就會在復(fù)制及丟棄該塊時執(zhí)行
)
從棧到堆
對于Block (用copy方法)
使用場景:向方法或函數(shù)的參數(shù)中傳遞Block時
不需手動復(fù)制的情況:
Cocoa框架的方法且方法名中含有usingBlock時
GCD的API
將block作為函數(shù)返回值返回時汇歹,將Block賦值給用__strong修飾的id類或Block類型成員變量時屁擅,編譯器會自動將對象的Block作為參數(shù)并調(diào)用_Block_copy函數(shù)(和copy效果一樣)
源存儲域 | 復(fù)制效果 |
---|---|
棧 | 棧 -> 堆 |
堆 | 引用計數(shù)增加 |
程序的數(shù)據(jù)區(qū)域 | 什么也不做 |
對于__block變量
跟隨Block移動:當(dāng)一個引用__block變量的Block從棧到堆時,__block變量也從棧到堆产弹,并持有該變量派歌;當(dāng)有另外一個也引用了該__block變量的Block從棧到堆時,該Block也持有該變量并且該變量引用計數(shù)加一痰哨,
參考資料:
《Objective-C高級編程》