Block 延長(zhǎng)生命周期引發(fā)線(xiàn)程不安全的的問(wèn)題

總結(jié)一下工作中遇到的問(wèn)題

block 是我們工作中常用的一個(gè)東西,使用它有很多注意點(diǎn),我今天聊下項(xiàng)目上線(xiàn)之后使用block引發(fā)一個(gè)崩潰問(wèn)題,

1.先來(lái)了解一下block捕獲auto變量

我們知道block會(huì)將局部auto變量捕獲到內(nèi)部, 內(nèi)部會(huì)強(qiáng)引用變量,這樣會(huì)造成循環(huán)引用的問(wèn)題,這是一個(gè)老生常談的問(wèn)題了,用__weak和__unsafe_unretained 都行但是后者是不安全的,只是在對(duì)象釋放的時(shí)候__weak會(huì)將引用的對(duì)象置為nil,而__unsafe_unretained不會(huì),這將會(huì)導(dǎo)致野指針的產(chǎn)生,,也就不多說(shuō)了


解決辦法是使用__weak弱應(yīng)用他,就可以解決循環(huán)引用的問(wèn)題,那么我們?cè)賮?lái)看一個(gè)現(xiàn)象,我開(kāi)啟一個(gè)子線(xiàn)程執(zhí)行任務(wù),我進(jìn)入一個(gè)界面后,在迅速返回,并且在子線(xiàn)程上模擬一個(gè)耗時(shí)操作,在的耗時(shí)操作的時(shí)間內(nèi)內(nèi)我們返回上一層讓我們的控制器銷(xiāo)毀,我們看下會(huì)發(fā)生什么事情,結(jié)果如下


由于弱應(yīng)用了self,在控制器被銷(xiāo)毀之后,對(duì)象被釋放了,所以無(wú)法保留,如果我們?nèi)匀幌雽?duì)對(duì)象進(jìn)行操作,那就要對(duì)對(duì)象進(jìn)行?;?如何進(jìn)行保活我相信作為一個(gè)iOS開(kāi)發(fā)者都知道的,在block內(nèi)部強(qiáng)引用這個(gè)變量,所以是在代碼塊(scope)里面都不會(huì)釋放,保證對(duì)象的生命周期,結(jié)果如下

本文的重點(diǎn)

看似很完美但是這樣寫(xiě)代碼就真的沒(méi)有問(wèn)題了嗎?

答案是否定的,這樣寫(xiě)只能說(shuō)在block塊里面任務(wù)執(zhí)行完畢時(shí)沒(méi)有任何問(wèn)題的,如果你block里面操作了這個(gè)資源,剛好這個(gè)資源會(huì)在其他地方也有使用就會(huì)造成資源搶奪在可能,嚴(yán)重的會(huì)造成app崩潰影響,為了說(shuō)明這個(gè)問(wèn)題我來(lái)演示一下這個(gè)現(xiàn)象

控制器A Push控制器B,不做多余的操作


代碼不變的情況下我一步操作,push完控制器我立刻pop我們的上一層控制器,也就是pop到我們的控制器A,當(dāng)然我控制器A的在生命周期的方法里面移除了最后一個(gè)元素

我們看下結(jié)果


結(jié)果肯定崩潰,說(shuō)明線(xiàn)程不安全,2個(gè)線(xiàn)程可以同時(shí)訪問(wèn)一個(gè)資源,解決資源搶奪的方案就是加鎖,數(shù)據(jù)庫(kù)使用databaseQueue保證線(xiàn)程安全訪問(wèn),當(dāng)然了還有種處理方案就是不要使用強(qiáng)引用,弱應(yīng)用它就行了,一個(gè)nil發(fā)出的消息是不會(huì)被響應(yīng)的,如果一定要用strongSelf來(lái)達(dá)到你項(xiàng)目中某些需求的話(huà),注意block持有對(duì)象的生命周期即可,做對(duì)應(yīng)的處理,

再次我要感謝bugly,如果沒(méi)有buggly,我無(wú)法發(fā)現(xiàn)這個(gè)問(wèn)題產(chǎn)生的原因,雖然能意思到可能是線(xiàn)程不安全的問(wèn)題,但是卻不知道是如何產(chǎn)生的,bugly除了可以實(shí)時(shí)的監(jiān)控崩潰,還有界面跟蹤功能,這個(gè)功能讓我精準(zhǔn)的定位到了意識(shí)到block延長(zhǎng)生命周期所產(chǎn)生的問(wèn)題,值得一提這個(gè)異常上報(bào)的埋點(diǎn)功能做的真的不錯(cuò)

當(dāng)然我們?cè)陧?xiàng)目中寫(xiě)代碼肯定不會(huì)怎么寫(xiě),一定會(huì)判斷一下是否為數(shù)組越界,項(xiàng)目還可以hook一些崩潰的方法,比如數(shù)組 objectAtIndex 方法減少你的項(xiàng)目在線(xiàn)上的崩潰率,對(duì)返回的消息做對(duì)應(yīng)的處理,在這里我就不啰嗦了,網(wǎng)上有很多這樣的處理方式

后記:記錄這個(gè)問(wèn)題希望對(duì)一些人能有所幫助

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容