block快的存儲(chǔ)位置(block入口的地址)可能存放在3個(gè)地方:代碼區(qū)(全局區(qū))、堆區(qū)、棧區(qū)(ARC情況下回自動(dòng)拷貝到堆區(qū)、因此ARC下只有兩個(gè)地方:代碼區(qū)和堆區(qū))
有三種常見(jiàn)的類型:
①<NSGlobalBlock: 0x102cef0b8>
存儲(chǔ)在程序的代碼段,全局區(qū);NSGlobalBlock:不會(huì)訪問(wèn)任何外部變量,比如:
void(^blockA)(void) = ^{
NSLog(@"just a block");
};
NSLog(@"%@", blockA);
②<NSMallocBlock: 0x60000025b120>
存儲(chǔ)在堆上。當(dāng)blcok的引用計(jì)數(shù)為0時(shí)會(huì)被銷毀,比如:
int value = 10;
void(^blockB)(void) = ^{
NSLog(@"just a block === %d",value);
};
NSLog(@"%@", blockB);
③<NSStackBlock: 0x7ffeecf0fad0>
存儲(chǔ)在棧上,NSStackBlock:在block內(nèi)部引用外部變量,除了函數(shù)作用域會(huì)被銷毀,引用導(dǎo)致奔潰,所以需要拷貝到堆上,比如:
// 強(qiáng)行在ARC上將一個(gè)block創(chuàng)建在棧上
void(^__weak blockC)(void) = ^{
NSLog(@"just a block === %d",value);
};
NSLog(@"%@", blockC);
//注意:在arc情況下,沒(méi)有NSStackBlock這個(gè)類型,如果有系統(tǒng)自動(dòng)copy成為NSMallocBlock,同時(shí)會(huì)拷貝代碼內(nèi)部變量如:
int base = 2;
base += 2;
long (^sums)(int,int) = ^ long (int a,int b){
return base + a + b;
};
base ++;
NSLog(@"%ld",sums(1,2));
//輸出的結(jié)果為 7 arc下提前拷貝base
需要特別注意的是,在ARC下,很多都已經(jīng)自動(dòng)幫我們Copy成了MallocBlock了,由于Block是默認(rèn)建立在棧上,所以如果離開(kāi)方法作用域就會(huì)釋放,如果要在外部調(diào)用,需要用copy指向它,這樣就拷貝到了堆區(qū),strong不具有拷貝功能