通过闭包传递并返回self替代[weak self],是否会产生循环引用?
这个写法会产生循环引用吗?
好问题!咱们来拆解一下你的代码逻辑,看看循环引用是怎么形成的:
为什么当前写法会有循环引用风险?
循环引用的核心是两个对象互相强引用,导致都无法被系统回收。结合你的代码来看:
- 假设调用
askToConfirm(from: self)的那个 ViewController(也就是代码里的self),对alertManager持有强引用(比如把它作为类属性)。 - 在
AlertManager的askToConfirm方法中,你创建的invitation对象会持有那个带[weak self]的闭包。 - 这个闭包会强引用传入的
vc(也就是你的 ViewController),同时还会强引用调用者传入的completion闭包——而你的completion闭包里又用到了vc(比如vc.model.confirm()),相当于completion也强引用了 ViewController。 - 最终形成的引用链是:
ViewController → alertManager → invitation → 闭包 → ViewController(或者加上completion的链路),这就形成了闭环,导致两者都无法被释放,造成内存泄漏。
怎么修改才能避免?
你想要避免在调用处写[weak self]的需求是合理的,只需要在AlertManager的闭包里,对传入的vc也做弱引用处理即可:
func askToConfirm<T>(from vc: T, completion: @escaping (T, Bool) -> ()) { // 这里给vc加上weak修饰 let invitation = pageItemFactory.createConfirmationPageItem() { [weak self, weak vc] accepted in self?.dismissAlert() // 先判断vc是否还存在,再执行completion guard let safeVC = vc else { return } completion(safeVC, accepted) } present(invitation) }
这样修改后,闭包里只持有vc的弱引用,不会再形成循环,同时调用处依然不需要写[weak self],完美满足你的需求。
另外要额外注意:如果alertManager是单例,这个问题会更严重——单例的生命周期和APP一致,强引用的ViewController永远不会被回收,内存泄漏会一直存在,所以这种场景下弱引用vc就更必要了。
内容的提问来源于stack exchange,提问作者Tometoyou
相关产品推荐
相关产品推荐

