在實際開發(fā)中顾复,使用Block比delegate和notification更簡潔贡耽。于是在項目中會大量的使用block侄刽。
1执虹、什么是block?
block
其實就是一個代碼塊唠梨,將要執(zhí)行的代碼封裝在這個代碼塊里面,等到需要的時候再去調(diào)用侥啤。block
也是OC對象当叭,官方文檔如下
2茬故、block要用copy修飾,還是用strong
block
本身是像對象一樣可以retain
和release
。但是蚁鳖,block
在創(chuàng)建的時候磺芭,它的內(nèi)存是分配在棧(stack)上,而不是在堆(heap)上
醉箕。他本身的作于域是屬于創(chuàng)建時候的作用域钾腺,一旦在創(chuàng)建時候的作用域外面調(diào)用block將導(dǎo)致程序崩潰。
- 使用
retain
也可以讥裤,但是block
的retain
行為默認是用copy
的行為實現(xiàn)的放棒,
因為block
變量默認是聲明為棧變量
的,為了能夠在block
的聲明域外使用己英,所以要把block拷貝(copy)到堆
间螟,所以說為了讓block屬性聲明和實際的操作一致
,最好聲明為copy
损肛。
3厢破、__block關(guān)鍵字的使用
在Block
的代碼塊內(nèi)不可以對外面的變量
進行更改的,使用__block
就能改變block
代碼塊中變量
的值
4、__block和__weak有什么區(qū)別治拿?
-
__block
不管是ARC
還是MRC
模式下都可以使用摩泪,可以修飾對象,還可以修飾基本數(shù)據(jù)類型劫谅。 -
__weak
只能在ARC
模式下使用见坑,也只能修飾對象(NSString)
,不能修飾基本數(shù)據(jù)類型(int)
同波。 -
__block對象
可以在block
中被重新賦值
鳄梅,__weak
不可以。
5未檩、Block的使用
@interface BrushViewController : BaseViewController
@property (nonatomic, copy) void (^getCardInfo)(NSDictionary *cardInfo);
@end
將block
聲明為copy
的原因是在代碼塊里面我可能會使用一些本地變量
戴尸。而block一開始是放在棧上的,只有copy后才會放到堆上冤狡。
如果不加copy
屬性孙蒙,當其所在棧被釋放的時候,這些本地變量將變得不可訪問悲雳。一旦代碼執(zhí)行到block內(nèi)部
就會出錯挎峦。
brush.getCardInfo=^(NSDictionary *info){
[self test];
};
像上面這段代碼,self
是一個本地變量
而不是block內(nèi)部變量
合瓢,如果聲明為assign
坦胶,代碼執(zhí)行到block內(nèi)部
就會出錯。
另外一個問題就是self
的引用計數(shù)會+1
。這樣會導(dǎo)致循環(huán)引用
顿苇。self持有brush峭咒,brush持有block,block持有self纪岁,結(jié)果就是內(nèi)存泄漏
凑队。
解決的辦法如下:
__block CurrentViewController* blockSelf = self;
brush.getCardInfo=^(NSDictionary *info){
[blockSelf test];
};
通過這個方式,告訴block這個變量的引用計數(shù)不要+1幔翰。
(__block
在ARC
和MRC
均可以使用漩氨,__weak
只能在ARC
下使用)
如果你使用的是ARC
,那么就應(yīng)該改成下面這樣:
__weak CurrentViewController* blockSelf = self;
brush.getCardInfo=^(NSDictionary *info){
[blockSelf test];
};