Swift ViewModel闭包捕获self应选weak还是unowned?内存管理疑问
问题解答
1. 当前写法是否存在问题
你目前全部使用[weak self]捕获的写法不存在安全问题,甚至是适配你当前异步网络请求场景的合理选择。
官方文档中关于优先使用unowned的表述有严格前提:被捕获的引用在闭包的整个生命周期内永远不会变为nil。你的场景中所有闭包都是网络请求的异步回调,执行时机完全依赖网络耗时,不受ViewModel生命周期控制,完全可能出现闭包执行时ViewModel已经被销毁的情况,不满足unowned的使用条件。
2. ViewModel场景内存管理最佳实践
- 对于执行时机不可控的异步回调(如网络请求、延迟执行任务),统一使用
[weak self]捕获,禁止使用unowned,避免野指针崩溃。 - 闭包内部可通过可选绑定解包self,避免频繁写
self?.的冗余代码:
request.execute { [weak self] result in guard let self = self else { return } // 后续直接使用self即可,无需添加可选符号 }
- 仅当闭包的生命周期和ViewModel完全绑定(比如闭包是ViewModel的内部存储属性,仅在ViewModel存活时会被调用,ViewModel销毁时闭包也会同步销毁),才可以使用
unowned降低可选处理的开销。
3. 是否可以强制解包self
绝对不可以强制解包。ViewModel存在被释放的可能性,强制解包会在self为nil时直接触发崩溃,完全不符合容错要求。
4. ViewModel被释放的常见场景
ViewModel作为和页面绑定的业务层对象,会在对应页面销毁且无其他强引用时被释放,典型场景包括:
- 导航栈中页面被pop,对应的UIViewController被销毁
- 模态弹出的页面被dismiss,对应的控制器被销毁
- SwiftUI中对应View的父容器刷新,旧的ViewModel实例被替换
这种场景下异步回调回来后,self?.调用会自动忽略后续逻辑,符合业务预期(已经退出的页面不需要再处理网络请求结果)。
内容的提问来源于stack exchange,提问作者dilldawg
相关产品推荐
相关产品推荐

