You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RxSwift.Observable的compactMap从闭包改为函数后出现内存泄漏问题

问题根源

重构后的代码产生了强引用循环(retain cycle),导致AppointmentViewModel实例无法被释放,deinit方法永远不会触发。

具体原因

  • 原有代码的compactMap传入的闭包明确加了[weak self]修饰,不会强持有ViewModel实例,不会产生循环引用。
  • 重构时你直接将实例方法selectAppointment(index:from:)作为参数传给了compactMap。Swift 中的实例方法本质是会自动强持有所属实例的柯里化函数,当你直接把实例方法当闭包传递时,相当于隐式捕获了self的强引用,没有任何弱引用/无主引用修饰。
  • 此时就形成了无法打破的引用环:ViewModel实例 -> 自身持有的disposeBag -> Rx订阅链 -> 被订阅链强持有的self(ViewModel实例)。就算你把外部的viewModel变量设为nil,环里的实例互相强持有,谁都不会被释放。

修复方案

不要直接传递实例方法,改成带[weak self]的闭包调用即可:

private func setupCellParamSelection() {
    selectedCellParamRelay
        .withLatestFrom(sortedCellParams) { ($0, $1) }
        .compactMap { [weak self] index, cellParams in
            try self?.selectAppointment(index: index, from: cellParams)
        }
        .bind(to: upcomingCellParamRelay)
        .disposed(by: disposeBag)
}

修复后再运行测试,viewModel设为nil时没有其他强引用会正常释放,deinit触发,disposeBag被销毁同时清理所有订阅,测试可以正常通过。

内容的提问来源于stack exchange,提问作者Bawenang Rukmoko Pardian Putra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 01:30:01