myBlk clang後轉換爲 Blcok的結構體類型的自動變量框架
__block 變量a clang 後轉換成 __block變量的結構體類型的自動變量async
_NSConcreteStackBlock 棧函數
_NSConcreteGlobalBlock 全局區(靜態區) 準確說是 .data區 .data區是放已被初始化的全局、靜態)spa
_NSConcreteMallocBlock 堆設計
沒有引用自動變量的block叫作NSGlobalBlock, (引用全局或者外部變量仍是NSGlobalBlock)對象
其他Block生成的Blcok 爲 NSStackBlock類對象, 且設置在棧區資源
這正是上一篇博客留下的問題:Blcok 超出變量做用域可存在的緣由?作用域
配置在棧區的Block, 其做用域結束時,該Block就被廢棄了。 __block 也是配置在棧區,做用域結束時一樣也會被廢棄。博客
全局區的block 做用域廣,因此不會有這種問題,可是全局Block 是不捕獲自動變量的。用的也少。it
那怎麼解決棧區Block 過了做用域銷燬的問題呢?
Blocks 提供了將Block 和 __block變量 從棧上 複製到 堆上 的方法 來解決這個問題。將棧上的Blcok 複製到堆上,這樣即便Block的變量做用域結束了,堆上的Block還能夠繼續存在。
這就解決了過了做用域銷燬的問題
在看__forwarding 的問題, __block變量用結構體成員變量__forwarding能夠實現不管__block變量配置在棧上仍是堆上,都能正確的訪問__block結構體變量。
棧區block copy 後從棧區到堆區
全局block copy 後什麼也不作
堆區block copy 後引用計數增長
因此 無論Block配置在何處,用copy都不會引發任何問題。可是copy是至關消耗CPU資源的,當Block在棧區可使用時,就不要copy進堆區。
且在 ARC中屢次copy 也沒有任何問題。 ARC中大部分狀況系統都幫你作了copy,只有 向方法或函數的參數傳遞Block時,系統不會自動copy。 可是若是在方法或函數中適當地複製了傳遞過來的參數,就不用在調用方法或函數前手動複製了。好比有些方法就爲咱們這麼設計了:
1.cocoa框架的方法且方法名中含有usingBlock的方法
2.GCD 的API
具體舉例:NSArray類的 enumerateObjectsUsingBlock 實例方法
GCD的 dispatch_async函數
都不須要手動複製。
須要手動複製的方法:
NSArray initWithObjects 實例方法上傳遞Block是須要手動複製
緣由是:block是棧區block 過了做用域,block就銷燬了。
解決辦法:將block 複製到堆區。