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
相关产品推荐
相关产品推荐

