其實在 swift 中也是有 野指針訪問僵尸對象造成崩潰的時候的
開發(fā)過程中,我 override 了一個 UIView 對象的removeFromSuperview()
本意是想在這個對象移除的時候 添加一個移除動畫 再移除.所以就刻意沒有寫 [weak self]
弱引用這個對象. 因為想完成動畫以后再移除.
可是
之前都是直接放在 keyWindow
上 , 今天的需求是放在一個控制器的 View 上面.
當這個重寫了 removeFromSuperview()
在沒有手動調(diào)用 view.removeFromSuperview()
方法 , 控制器先 deinit
之后. Swift 也同樣的將這個對象的內(nèi)存給釋放了.
所以
當這個view
對象被系統(tǒng) deinit 之前 , 他的 superView 對他執(zhí)行了 subview.removeFromSuperview()
方法. 然后 deinit
執(zhí)行 , 對象被回收.
于是
當異步執(zhí)行的 UIView.animate
方法執(zhí)行到 Complete
閉包時,對這個對象發(fā)送任何消息,都是在訪問一個僵尸對象.最后造成的就是 BAD_ACCESS
程序閃退
具體的代碼:
尋找 BUG 思路
99% 的 程序崩潰都來源于數(shù)組越界. 在 swift 中 其實有很多來源于強制解包. 但是我寫 swift 時 幾乎不用!
來強制解包. 所以在執(zhí)行 deinit 前后有哪些函數(shù)調(diào)用 就是最可疑的.
- 第一步 : 尋找導致崩潰的函數(shù)大致范圍. 將代碼暫存,并恢復(fù)到上一次提交,發(fā)現(xiàn)這個 BUG 依然存在. 那么一定不是最近寫的幾行代碼導致的
- 打斷點,看內(nèi)存堆棧 : 看看關(guān)鍵幾個函數(shù)的調(diào)用順序
- 找到目標函數(shù),嘗試修改
由于這段代碼是我自己寫的,在進行第一步之后,我的懷疑目標就落在了這個函數(shù)上面.
可是之前都執(zhí)行的很好,唯一的不同就是 這次添加在一個 控制器的View
上面.
那么在控制器釋放的時機出現(xiàn)的問題,應(yīng)該就是在這段代碼了.
- 嘗試修改之后,順便發(fā)現(xiàn)
[weak super]
這樣的寫法果然是不允許的. 于是封裝了一個函數(shù),使用self?.
去訪問