Swift中deinit方法未被调用如何仅修改一行代码完成修复
Swift deinit未触发问题修复
根因分析
该问题是ARC内存管理机制下的经典强引用循环场景:
Handler类实例强持有自身的closure属性- 闭包默认会强持有内部捕获的
self(即当前Handler实例本身)
二者互相强持有导致引用计数永远无法降到0,因此即使外部将handler置为nil,实例也无法被释放,deinit方法不会触发。
修复方法
仅需要修改1行代码,在闭包的捕获列表中声明对self的非强持有规则,打破引用循环即可实现需求,可选两种修改方案:
方案1(满足仅修改1行要求)
如果可以确认闭包的生命周期不会超过Handler实例的生命周期,直接修改闭包声明行增加[unowned self]捕获即可,不需要调整闭包内部的原有代码:
closure = { [unowned self] in
方案2(更安全,推荐生产环境使用,总计修改2行)
如果无法保证闭包调用时self一定存在,优先使用弱引用避免崩溃,修改闭包声明行增加[weak self]捕获:
closure = { [weak self] in
同步把闭包内的调用改为可选解包即可:
self?.obj.greeting()
修改完成后运行代码即可触发deinit,输出期望结果。如果需要两个输出内容中间有空格,可调整deinit中的字符串为" Handler is being deinitialized."即可。
内容的提问来源于stack exchange,提问作者David S
相关产品推荐
相关产品推荐

