block本身是像對(duì)象一樣可以retain絮爷,和release翼雀,但是棧block和全局block這些操作都無(wú)效而姐,只有堆block操作有效膘融,雖然retainCount始終是1但是內(nèi)存管理器中仍然增減計(jì)數(shù)芙粱。使用retain也可以,但是block的retain行為默認(rèn)是用copy的行為實(shí)現(xiàn)的氧映,
因?yàn)閎lock引用外部變量時(shí)默認(rèn)是聲明為棧Block的春畔,為了能夠在block的聲明域外使用,所以要把block拷貝(copy)到堆岛都,所以說(shuō)為了block屬性聲明和實(shí)際的操作一致律姨,最好聲明為copy。
一臼疫、globalBlock無(wú)論什么操作都是globalBlock
二择份、block在什么情況下會(huì)copy到mallocBlock?
1.在block中如果有引用外部變量(默認(rèn)聲明為棧Block),且烫堤,block被賦值給__strong對(duì)象 或者 [block copy]
2.棧Block作為方法荣赶、函數(shù)的返回值,其實(shí)這是一種copy操作
3.GCD或UsingBlock:方法引用block鸽斟,其實(shí)這也是線程或者其他對(duì)象強(qiáng)引用了Block
只有stackBlock才有可能變?yōu)閙allocBlock讯壶。
代碼1
void(^myBlock)(void) = ^() {
printf("ss");
};
myBlock();
這里的block沒(méi)有引用外部變量,存儲(chǔ)在代碼中湾盗,為全局類型,NSGlobalBlock
代碼2
char *str = "qqq";
void(^myBlock)(void) = ^{
NSLog(@"%s",str);
};
myBlock();
表面看這里的block引用外部變量立轧,存儲(chǔ)在棧中格粪,離開(kāi)作用域就會(huì)釋放;
但是實(shí)際上這里的myBlock是存放在堆中NSMallocBlock氛改,原因是因?yàn)檫@里在將block賦值給myBlock2時(shí)帐萎,在ARC下系統(tǒng)將block copy到了堆里
代碼3
char *str = "aass";
//__NSStackBlock__
NSLog(@"%@",^{printf("%s",str);});
//__NSStackBlock__,直接在棧中被調(diào)用
^{printf("%s",str);}();
這里輸出的block就是存放在棧里面了,這里沒(méi)有賦值操作
代碼4
char *str = "qqq";
//__NSStackBlock__胜卤,這里雖然進(jìn)行了賦值操作疆导,但是賦值的對(duì)象是__weak
__weak Blk blockWeak = ^() {
printf("%s",str);
};
blockWeak();
//__NSMallocBlock__,這里給__strong block對(duì)象賦值
__strong Blk blockStrong = ^() {
printf("%s",str);
};
blockStrong();
代碼5
__block int h = 9;
//__NSStackBlock__,直接在棧中被調(diào)用,因?yàn)闆](méi)有copy也沒(méi)有給__strong對(duì)象賦值
^{h = 11;printf("%d",h);}();
//__NSStackBlock__,直接在棧中被調(diào)用葛躏,因?yàn)闆](méi)有copy也沒(méi)有給__strong對(duì)象賦值
NSLog(@"%@",^{h = 12;printf("%d",h);});