根據(jù)Block的存儲(chǔ)域,可以分為三類:
1.NSGlobalBlock? 全局區(qū)(程序的數(shù)據(jù)區(qū))
2.NSStackBlock? 棧區(qū)域(只在MRC下存在),超出變量的作用域,棧上的Block和__block類型變量都被銷毀.
3.NSMallocBlock 堆區(qū)域, 在變量作用域結(jié)束時(shí),變量不受影響
那么我們平時(shí)創(chuàng)建的Block屬于哪一種呢?
總結(jié)下,生成在全局區(qū)block的情況:
?1.定義全局變量的時(shí)候有block語(yǔ)法
? 2.block語(yǔ)法的表達(dá)式中沒(méi)有使用截獲的自動(dòng)變量時(shí)
其余的block都是棧區(qū)Block.那么堆區(qū)的Block又是怎么回事呢?
其實(shí),一般在ARC開啟的情況下,在棧區(qū)創(chuàng)建的Block都會(huì)復(fù)制到堆區(qū)(系統(tǒng)自動(dòng)進(jìn)行),以防止超出作用域后block變量會(huì)被銷毀而不能正常使用.一般,以下幾種情況下,棧區(qū)的Block會(huì)復(fù)制到堆區(qū):
1.調(diào)用Block的copy實(shí)例方法(ARC自動(dòng)調(diào)用),或者Block_copy方法
2.Block作為函數(shù)返回值
3.將Block的值賦給__strong修飾的id類型或Block類型成員變量
4.將方法中含有usingBlock的Cocoa框架方法或GCD的API中傳遞Block時(shí)
MRC情況下Block從棧區(qū)到堆區(qū)的復(fù)制:
Block_copy(block體),為了避免內(nèi)存泄漏, Block_copy必須與Block_release(block)結(jié)合使用.
同時(shí), Foundation框架提供了兩個(gè)與上述函數(shù)作用相同的方法:
block = [block體 copy]; ?[block release] (ARC下的自動(dòng)復(fù)制就是調(diào)用了copy方法)
__block:
Block語(yǔ)法表達(dá)式中使用的局部變量被作為成員變量追加到Block所在的結(jié)構(gòu)體中,因而不能修改外面的局部變量(基本數(shù)據(jù)類型);
當(dāng)局部變量使用__block修飾時(shí),其地址被作為成員變量追加到Block所在的結(jié)構(gòu)體中,因此可以對(duì)該局部變量進(jìn)行修改