關(guān)于block
void pr (int (^block)(void)) {
printf("%d\n",block());
}
int (^g)(void) = ^{
return 100;
};
void func1 (int n) {
int (^b1)(void) = ^{
return n;
};
pr(b1);
g = b1;
}
void func2 (int n) {
int a = 10;
int (^b2)(void) = ^{
return n*a;
};
pr(b2);
}
int main(int argc, char * argv[]) {
@autoreleasepool {
pr(g);
func1(15);
func2(5);
pr(g);
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
這段代碼在MRC和ARC下的輸出結(jié)果是不一樣的
MARC環(huán)境下的輸出結(jié)果

image.png
ARC環(huán)境下的輸出結(jié)果

image.png
之所以在MRC環(huán)境下輸出的結(jié)果不為 100、15、50、15,是因為函數(shù)內(nèi)的block的生命周期和自動變量一樣,當執(zhí)行函數(shù)時block的內(nèi)存會被保存在棧上,當func1執(zhí)行完畢后塊b1的生命周期也隨之結(jié)束。(我猜想)當再次調(diào)用pr(g)時調(diào)用的是依舊保留在棧區(qū)的pr函數(shù)和pr函數(shù)中保存的b2(此時該內(nèi)存塊還沒有被從棧中彈出),但是如果此時pr已經(jīng)出棧,則會出現(xiàn)錯誤。
如果想要解決該錯誤只需使用Block_copy()函數(shù)對b1進行一次拷貝,Block_copy()函數(shù)會講棧區(qū)的block拷貝一份到堆區(qū)此時g便指向?qū)^(qū)的b1了。
void func1 (int n) {
int (^b1)(void) = ^{
return n;
};
pr(b1);
g = Block_copy(b1);
}

image.png
而在ARC環(huán)境下會自動對block進行一次拷貝。