Q: 什么是Block旱捧?
A: Block是將函數(shù)及其執(zhí)行上下文封裝起來(lái)的對(duì)象潘悼。
Q: 怎樣理解Block調(diào)用衡载?
A: Block調(diào)用就是函數(shù)的調(diào)用
Q: Block的一大特性是截獲變量阔蛉,那么系統(tǒng)關(guān)于Block截獲變量是怎樣實(shí)現(xiàn)的瓣喊?
Q: 會(huì)使用__block修飾符花履,這修飾符用于做什么芽世?
Q: 什么時(shí)候需要對(duì)Block進(jìn)行copy操作?
Q: 棧Block诡壁,堆Block是否了解济瓢?
isa指針,是Block是對(duì)象的標(biāo)志
FuncPtr是函數(shù)指針妹卿,會(huì)指向具體的函數(shù)實(shí)現(xiàn)旺矾。
通過(guò)函數(shù)指針,得到相應(yīng)的函數(shù)執(zhí)行體夺克。
截獲變量
Q:對(duì)Block截獲變量的特性是否有了解箕宙?
A:
1).對(duì)于基本數(shù)據(jù)類型的局部變量截獲其值 (值類型)
2).對(duì)于對(duì)象類型的局部變量連同所有權(quán)修飾符一起截獲(例如__unsafe_unretained id unsafe_obj = nil;
__strong id strong_obj = nil; 循環(huán)引用跟所有權(quán)修飾符一起截獲是有關(guān)的)
3).以指針形式截獲局部靜態(tài)變量(引用類型)
4).不截獲全局變量,靜態(tài)全局變量
__block修飾符
-
一般情況下铺纽,對(duì)被截獲變量進(jìn)行賦值操作柬帕,需要加__block修飾符
1.使用,不需要__block
2.賦值室囊,需要__block
3.對(duì)變量賦值雕崩,需要__block
4.對(duì)變量賦值,不需要__block
__block修飾的變量變成了對(duì)象
棧上的__forwarding指針指向自己融撞。
__forwarding指針是用來(lái)做什么的盼铁?
Block內(nèi)存管理
Q:何時(shí)需要對(duì)block進(jìn)行copy操作?
對(duì)于不同類型的block尝偎, copy的結(jié)果也不一樣饶火。
Q:當(dāng)對(duì)棧上block進(jìn)行copy操作后,在MRC環(huán)境下致扯,是否會(huì)引起內(nèi)存泄漏呢肤寝?
A:會(huì)。copy操作后抖僵, 堆上的block沒(méi)有其他額外的成員變量指向它鲤看,跟alloc出一個(gè)對(duì)象,沒(méi)有給出相應(yīng)的release操作一樣耍群,產(chǎn)生內(nèi)存泄漏义桂。
棧上__block變量的copy
Q:棧上的__forwarding指針的用處?
A: 棧上的__forwarding指針指向的是堆上的block變量蹈垢,堆上的__forwarding指針指向的是自身慷吊。
如果要修改棧上block,如果做過(guò)copy操作曹抬,實(shí)際上修改的就不是棧上的__forwarding對(duì)應(yīng)的值溉瓶,而是通過(guò)通過(guò)棧上block的__forwarding指針找到堆上的__forwarding變量,然后對(duì)堆上的multiplier值進(jìn)行修改,比如改成4堰酿。
同樣的疾宏,如果是__block變量,由于被成員變量持有触创,當(dāng)我們?cè)谄渌胤秸{(diào)用__block變量的修改灾锯,實(shí)際是通過(guò)自身的__forwarding指向來(lái)修改的。
__forwarding存在的意義
Block循環(huán)引用
由于block對(duì)其截獲的變量嗅榕,是連其所有權(quán)修飾符一并截獲顺饮。
因此,block內(nèi)部的持有的變量凌那,也是__weak類型兼雄。
Q:以下代碼有什么問(wèn)題?
A:在MRC下帽蝶,不會(huì)產(chǎn)生循環(huán)引用赦肋,在ARC下,會(huì)產(chǎn)生循環(huán)引用励稳,引起內(nèi)存泄漏佃乘。
這個(gè)解決方案的原理是,在block內(nèi)部把blockSelf置為nil驹尼,從而斷開(kāi)了對(duì)對(duì)象的持有趣避。但是有一點(diǎn)很重要,如果一直不調(diào)用block, 就沒(méi)機(jī)會(huì)斷開(kāi)對(duì)象的持有新翎,也就無(wú)法解決循環(huán)引用了
總結(jié)
Q:為什么block會(huì)產(chǎn)生循環(huán)引用程帕?
A:當(dāng)前block對(duì)當(dāng)前某一對(duì)象進(jìn)行截獲,block會(huì)對(duì)對(duì)應(yīng)變量強(qiáng)引用地啰,當(dāng)前block又由于當(dāng)前對(duì)象對(duì)其有一個(gè)強(qiáng)引用愁拭,因此就產(chǎn)生了一種自循環(huán)引用的循環(huán)引用問(wèn)題,可以聲明為_(kāi)_weak變量來(lái)進(jìn)行循環(huán)引用消除亏吝。如果定義了__block修飾符岭埠,一種是在MRC下,MRC不會(huì)產(chǎn)生循環(huán)引用蔚鸥,一種是在ARC下惜论,可以通過(guò)斷環(huán)的方式解除對(duì)應(yīng)循環(huán)引用。有一個(gè)弊端株茶,如果block一直不能被調(diào)用来涨,循環(huán)引用是不能被解除的图焰。
Q:你都遇到過(guò)哪些循環(huán)引用启盛,是怎么解決的?
A:
1). NSTimer
2). block循環(huán)引用, __weak解除