Swift报错:Cannot Form Weak Reference To Instance Of Class 问题求解
问题触发原因
这个报错的核心是:Objective-C运行时不允许对已经进入回收流程的对象生成弱引用,你遇到的崩溃属于deinit中访问lazy属性导致的典型问题:
- 你用
lazy关键字定义了stopwatch,它的初始化时机是第一次被访问的时候 - 你的
stopwatch初始化闭包使用了[weak self]捕获当前控制器实例,初始化时会尝试对控制器生成弱引用 - 你在控制器的
deinit方法中调用了stopwatch.stop(),如果控制器销毁前stopwatch从来没有被访问过,这时候就会触发stopwatch的lazy初始化 - 此时控制器已经进入dealloc回收流程,运行时不允许再生成它的弱引用,直接抛出异常崩溃
你只有按钮跳转时才复现的原因也很明确:
- 重启应用时直接加载
HomeViewController,正常使用过程中会触发stopwatch初始化,deinit时不会重复走初始化逻辑 - 从按钮跳转替换
rootViewController时,旧的控制器会被立刻回收,如果旧控制器从创建到销毁都没有触发过stopwatch的访问(比如没有点击过启停按钮),deinit访问stopwatch就会触发崩溃
修复方案
任选一种适配即可:
- 提前触发
stopwatch初始化:在HomeViewController的viewDidLoad方法中随便访问一次stopwatch,比如加一行_ = stopwatch,确保deinit时不会再走初始化流程 - 去掉
stopwatch的lazy修饰:调整Stopwatch的构造方式,不需要依赖控制器实例提前初始化 - 调整stop逻辑的调用时机:不要在deinit中调用
stopwatch.stop(),改在viewWillDisappear等生命周期方法中,提前在控制器进入回收前停止计时器
内容的提问来源于stack exchange,提问作者swiftnooby
相关产品推荐
相关产品推荐

