Block 存儲域 copy入堆的做用

myBlk   clang後轉換爲  Blcok的結構體類型的自動變量框架

 

 

__block 變量a   clang 後轉換成  __block變量的結構體類型的自動變量async

 

他們都在存儲在棧區上

 

 

_NSConcreteStackBlock     棧函數

_NSConcreteGlobalBlock   全局區(靜態區)  準確說是 .data區 .data區是放已被初始化的全局、靜態)spa

_NSConcreteMallocBlock   堆設計

 

什麼樣的Block 設置在全局區、什麼樣的在棧區??

沒有引用自動變量的block叫作NSGlobalBlock, (引用全局或者外部變量仍是NSGlobalBlock)對象

其他Block生成的Blcok 爲 NSStackBlock類對象, 且設置在棧區資源

 

配置在堆區上的Block 類 什麼時候使用?

這正是上一篇博客留下的問題: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 複製到堆區。

相關文章
相關標籤/搜索