來著唐巧的技術(shù)博客
閱博筆記,助于記憶和回顧
什么是block
In programming languages, a closure is a function or reference to a function together with a referencing environment—a table storing a reference to each of the non-local variables (also called free variables or upvalues) of that function.
閉包是一個函數(shù)或者想象一個函數(shù)指針,它擁有一個函數(shù)執(zhí)行時的上下文(自己認(rèn)為是函數(shù)執(zhí)行時的外部變量)
block的內(nèi)部數(shù)據(jù)結(jié)構(gòu)
struct Block_descriptor {
unsigned long int reserved;
unsigned long int size;
void (*copy)(void *dst, void *src);
void (*dispose)(void *);
};
struct Block_layout {
void *isa; //isa指針,所有對象都有的指針,用于實現(xiàn)對象相關(guān)的功能
int flags; //用于按bit位表示一些block的附加信息
int reserved;//保留變量
void (*invoke)(void *, ...);//函數(shù)指針,指向具體的block實現(xiàn)的函數(shù)調(diào)用地址
struct Block_descriptor *descriptor;//表示該 block 的附加描述信息,主要是 size 大小,以及 copy 和 dispose 函數(shù)的指針
/* Imported variables. */ //block可以訪問它的局部變量,將需要在函數(shù)中用到的外部變臉復(fù)制到了結(jié)構(gòu)體中
};
block的三種類型
- _NSConcreteGlobalBlock 全局的靜態(tài) block,不會訪問任何外部變量。
- _NSConcreteStackBlock 保存在棧中的 block,當(dāng)函數(shù)返回時會被銷毀。
- _NSConcreteMallocBlock 保存在堆中的 block,當(dāng)引用計數(shù)為 0 時會被銷毀。
當(dāng)不訪問外部任何變量時
MRC環(huán)境下block類型是_NSConcreteStackBlock
ARC環(huán)境下block類型是_NSConcreteGlobalBlock。
當(dāng)訪問外部變量時
MRC環(huán)境下block類型是_NSConcreteStackBlock
ARC環(huán)境下block類型是_NSConcreteMallocBlock
訪問的外部變量時,其實是拷貝了外部的變量,所以改變block實現(xiàn)體時的外部變量,并不會對外部變量造成影響
在ARC中其實在block創(chuàng)建時就會默認(rèn)執(zhí)行block copy,這時block就會從棧區(qū)拷貝到堆區(qū),而block的類型也會從_NSConcreteStackBlock變成_NSConcreteMallocBlock
__block
當(dāng)引用的外部變量是由__block 修飾的時候,那么block內(nèi)部就會復(fù)制外部變量的地址而不是值了。而且如果你沒有用修飾__block,那么你只能使用這些“變量”,而不能修改他
__block和__weak的區(qū)別
- __block不管是ARC還是MRC模式下都可以使用,可以修飾對象,還可以修飾基本數(shù)據(jù)類型。
- __weak只能在ARC模式下使用,也只能修飾對象(NSString),不能修飾基本數(shù)據(jù)類型(int)。
- __block對象可以在block中被重新賦值,__weak不可以。
- __block對象在ARC下可能會導(dǎo)致循環(huán)引用,非ARC下會避免循環(huán)引用,__weak只在ARC下使用,可以避免循環(huán)引用。
__block其實就是拷貝了外部變量的地址,在ARC下,就很有可能會引起循環(huán)引用了,self擁有block,而block擁有self。這時在block實現(xiàn)體內(nèi)self會被retain,但是在·MRC時__block修飾的self在則不會被retain。
所以在ARC環(huán)境下循環(huán)引用的地方還是用__weak比較安全