Block的類
類 | 設(shè)置對(duì)象的儲(chǔ)存域 |
---|---|
_NSConcreteStackBlock |
棧區(qū) |
_NSConcreteGlobalBlock |
程序的數(shù)據(jù)區(qū)(全局區(qū)) |
_NSConcreteMallocBlock |
堆區(qū) |
Block分配的規(guī)律
Block不論在ARC下還是在MRC下贡羔,都會(huì)視情況被分配到這三種區(qū)中枢步。我總結(jié)了分配在各種區(qū)的條件债蓝,如下:
-
NSConcreteGlobalBlock
:無(wú)論此block是否被持有祝峻,block內(nèi)沒(méi)有引用外部變量 -
NSConcreteStackBlock
: 此block必須未被持有枯夜,并且引用了外部變量 -
NSConcreteMallocBlock
:此block必須被持有挺智,并且引用了外部變量
Block執(zhí)行過(guò)copy后的情況
Block的類 | 副本源的配置儲(chǔ)存域 | 復(fù)制效果 |
---|---|---|
_NSConcreteStackBlock |
棧區(qū) | 從棧復(fù)制到堆 |
_NSConcreteGlobalBlock |
全局區(qū) | 什么也不做 |
_NSConcreteMallocBlock |
堆區(qū) | 引用計(jì)數(shù)增加 |
棧上的Block什么時(shí)候會(huì)被復(fù)制到堆
- 調(diào)用Block的
copy
實(shí)例方法 - Block作為函數(shù)返回值返回時(shí)
- 將Block賦值給附有
__strong
修飾符id
類型的類或Block類型成員變量時(shí) - 在方法名中含有
usingBlock
的Cocoa
框架方法或Grand Central Dispatch
的API中傳遞Block時(shí)
接下來(lái)就結(jié)合代碼來(lái)分析Block的內(nèi)存分配祷愉。
等號(hào)左側(cè)在OC默認(rèn)情況下屬于強(qiáng)指針,用__weak修飾后變成弱指針赦颇,右側(cè)Block不會(huì)被持有二鳄,并且Block引用了外部變量,所以會(huì)被分配在棧區(qū)
int temp = 10;
__weak void(^blk_t1)(void) = ^{
NSLog(@"%d",temp);
};
NSLog(@"1===%@",blk_t1);
等號(hào)左側(cè)在OC默認(rèn)情況下屬于強(qiáng)指針媒怯,右側(cè)block被持有订讼,引用外部變量就分配在堆區(qū)
int temp = 10;
void(^blk_t)(void) = ^{
NSLog(@"%d",temp);
};
blk_t();
NSLog(@"2===%@",blk_t);
等號(hào)左側(cè)在OC默認(rèn)情況下屬于強(qiáng)指針,右側(cè)block被持有扇苞,不引用外部變量就分配在全局區(qū)
void(^blk_tt)(void) = ^{
};
NSLog(@"3===%@",blk_tt);
此block未被持有欺殿,且引用了外部變量寄纵,所以分配在棧區(qū)
int temp = 10;
NSLog(@"4===%@",^{
NSLog(@"%d",temp);
});
棧區(qū)的block在執(zhí)行copy后會(huì)被分配到堆區(qū)
int temp = 10;
NSLog(@"5===%@",[^{
NSLog(@"%d",temp);
} copy]);
等號(hào)左側(cè)在OC默認(rèn)情況下屬于強(qiáng)指針,右側(cè)block被持有脖苏,block內(nèi)部未引用外部變量擂啥,被分配到全局區(qū),執(zhí)行copy后依然在全局區(qū)
void (^blk_ttt)(void) = ^() {
};
blk_ttt();
NSLog(@"\n6===\n拷貝前%@\n拷貝后%@",blk_ttt,[blk_ttt copy]);
block使用內(nèi)部局部變量帆阳,未引用外部變量哺壶,依然是全局block
void (^blk_tttt)(void) = ^{
int b = 20;
NSLog(@"%d",b);
};
blk_tttt();
NSLog(@"7===%@",blk_tttt);
block內(nèi)部使用傳進(jìn)來(lái)的參數(shù),并不會(huì)持有該參數(shù)蜒谤,此block在使用了參數(shù)后依然是全局block
NSString *str = @"I love China!";
void (^blk_ttttt)(NSString *) = ^(NSString *param){
NSLog(@"%@",param);
};
blk_ttttt(str);
NSLog(@"8===%@",blk_ttttt);