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

如何创建永不停止发射事件的Bool类型Observable且避免内存泄漏?

解决方案:让Bool Observable永久发射且避免内存泄漏

首先,你完全不需要放弃使用disposeBag——这恰恰是避免内存泄漏的核心!我们的目标是让isAgentAvailable这个Observable永远不会发送completed或error事件(这类事件会导致订阅自动终止),同时让订阅和视图生命周期绑定,彻底杜绝泄漏问题。

这里给你两个可行的方案:

方案1:改造现有Observable让它永不终止

如果你的isAgentAvailable可能会因为某些逻辑触发completed或error,可以通过RxSwift的操作符让它“持续存活”:

viewModel.outputs.isAgentAvailable
    // 捕获所有错误,替换为一个永不发射任何事件的Observable
    .catch { _ in Observable.never() }
    // 在原Observable完成后,拼接一个永不结束的Observable,维持订阅活跃状态
    .concat(Observable.never())
    .subscribe(
        onNext: { [unowned self] isAgentAvailable in
            if isAgentAvailable {
                self.liveChatButton.isEnabled = true
                self.isAgentAvailableLabel.text = agentAvailableText
            } else {
                self.liveChatButton.isEnabled = false
                self.isAgentAvailableLabel.text = agentUnavailableText
                self.liveChatButton.alpha = 0.5
            }
        }
    ).disposed(by: self.disposeBag)

Observable.never()会创建一个永远不会发送任何事件(包括completed/error)的Observable,这样就算原Observable完成或出错,整个序列也不会终止,订阅会一直保持活跃。

方案2:改用Relay(推荐,若可修改ViewModel)

如果你的ViewModel允许调整,推荐用BehaviorRelay<Bool>替代普通Observable。Relay本身就设计为永不终止(它不会发送completed或error事件),天生适配这种需要持续发射状态的场景:

在ViewModel中定义:

class ViewModel {
    let outputs = Outputs()
    
    struct Outputs {
        // 初始值根据业务需求设置
        let isAgentAvailable = BehaviorRelay<Bool>(value: false)
    }
    
    // 示例:更新在线状态的方法
    func updateAgentAvailability(_ available: Bool) {
        outputs.isAgentAvailable.accept(available)
    }
}

订阅代码:

viewModel.outputs.isAgentAvailable
    .subscribe(
        onNext: { [unowned self] isAgentAvailable in
            if isAgentAvailable {
                self.liveChatButton.isEnabled = true
                self.isAgentAvailableLabel.text = agentAvailableText
            } else {
                self.liveChatButton.isEnabled = false
                self.isAgentAvailableLabel.text = agentUnavailableText
                self.liveChatButton.alpha = 0.5
            }
        }
    ).disposed(by: self.disposeBag)

Relay会持续发射新的状态值,直到持有它的ViewModel被释放;而你的订阅因为绑定到disposeBag,会在视图控制器销毁时自动取消,完全不会有内存泄漏的风险。

为什么绝对不能跳过disposeBag?

你说得非常对,不加入disposeBag会导致订阅永远无法被释放,持续持有视图控制器的引用,最终造成内存泄漏。上面的方案既保证了Observable能持续发射事件,又通过disposeBag和视图生命周期绑定,完美兼顾了需求和内存安全。

内容的提问来源于stack exchange,提问作者Sara

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 11:12:43