block的本質(zhì)
block本質(zhì)上也是一個OC對象,它內(nèi)部也有個isa指針。block是封裝了函數(shù)調(diào)用以及函數(shù)調(diào)用環(huán)境的OC對象。
block的變量捕獲(capture)
為了保證block內(nèi)部能夠正常訪問外部的變量,block有個變量捕獲機制。
例子:

block的類型
block有3種類型,可以通過調(diào)用class方法或者isa指針查看具體類型,最終都是繼承自NSBlock類型。
1、NSGlobalBlock ( _NSConcreteGlobalBlock )全局區(qū)
2、NSStackBlock ( _NSConcreteStackBlock )堆區(qū)
3、NSMallocBlock ( _NSConcreteMallocBlock )棧區(qū)

每一種類型的block調(diào)用copy后的結(jié)果如下所示

對象類型的auto變量
當block內(nèi)部訪問了對象類型的auto變量時:
如果block是在棧上:將不會對auto變量產(chǎn)生強引用。
如果block被拷貝到堆上:
1、會調(diào)用block內(nèi)部的copy函數(shù)。
2、copy函數(shù)內(nèi)部會調(diào)用_Block_object_assign函數(shù)。
3、_Block_object_assign函數(shù)會根據(jù)auto變量的修飾符(__strong、__weak、__unsafe_unretained)做出相應(yīng)的操作,形成強引用(retain)或者弱引用。
如果block從堆上移除
1、會調(diào)用block內(nèi)部的dispose函數(shù)。
2、dispose函數(shù)內(nèi)部會調(diào)用_Block_object_dispose函數(shù)。
3、Block_object_dispose函數(shù)會自動釋放引用的auto變量(release)。
__block修飾符
__block可以用于解決block內(nèi)部無法修改auto變量值的問題,__block不能修飾全局變量、靜態(tài)變量(static),編譯器會將__block變量包裝成一個對象。

__block的內(nèi)存管理
當block在棧上時,并不會對__block變量產(chǎn)生強引用。
當block被copy到堆時,會調(diào)用block內(nèi)部的copy函數(shù),copy函數(shù)內(nèi)部會調(diào)用_Block_object_assign函數(shù),_Block_object_assign函數(shù)會根據(jù)所指向?qū)ο蟮男揎椃╛_strong、__weak、__unsafe_unretained)做出相應(yīng)的操作,形成強引用(retain)或者弱引用(注意:這里僅限于ARC時會retain,MRC時不會retain)。


__block的__forwarding指針

循環(huán)引用問題
ARC
用__weak、__unsafe_unretained解決

MRC
用__unsafe_unretained解決
用__block解決