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

如何阻止BehaviourRelay重排数组后的accept操作触发发射?

解决BehaviourRelay重排数组后触发UI重建的问题

针对你遇到的重排数组后调用accept导致UI组件重建的问题,可以通过以下几种方式拦截此次特定的发射操作:

方案一:使用中间代理Relay + 开关控制临时拦截发射

新增一个中间代理Relay,让UI组件订阅这个代理,通过开关控制是否转发原Relay的事件。在重排数组时关闭开关,完成更新后再打开:

// 定义开关和代理Relay
let shouldPublish = BehaviorRelay(value: true)
let designerDressProxy = PublishRelay<[MyCustomObjects]>()

// 绑定原Relay到代理,仅当开关开启时转发
designerDress
    .filter { _ in shouldPublish.value }
    .bind(to: designerDressProxy)
    .disposed(by: disposeBag)

// UI组件订阅代理Relay
designerDressProxy
    .subscribe(onNext: { dresses in
        // 更新UI的逻辑
    })
    .disposed(by: disposeBag)

// 重排数组时的操作
shouldPublish.accept(false)
var tempArray = designerDress.value
tempArray.reorderAsperMywish()
designerDress.accept(tempArray)
shouldPublish.accept(true)

方案二:自定义支持静默更新的BehaviourRelay

实现一个自定义Relay,添加不触发发射的更新方法,直接修改内部值而不通知订阅者:

class SilentBehaviourRelay<Element>: ObservableType {
    private let underlyingRelay: BehaviorRelay<Element>
    private var currentValue: Element
    
    init(value: Element) {
        currentValue = value
        underlyingRelay = BehaviorRelay(value: value)
    }
    
    // 对外暴露的当前值
    var value: Element {
        get { currentValue }
        set { currentValue = newValue }
    }
    
    // 常规accept,会触发发射
    func accept(_ newValue: Element) {
        currentValue = newValue
        underlyingRelay.accept(newValue)
    }
    
    // 静默更新,仅修改值不触发发射
    func acceptSilently(_ newValue: Element) {
        currentValue = newValue
    }
    
    // 实现ObservableType协议
    func subscribe<Observer>(_ observer: Observer) -> Disposable where Observer: ObserverType, Element == Observer.Element {
        underlyingRelay.subscribe(observer)
    }
    
    var asObservable: Observable<Element> {
        underlyingRelay.asObservable()
    }
}

将原有的designerDress替换为这个自定义Relay,重排时调用静默更新:

// 初始化时替换
let designerDress = SilentBehaviourRelay(value: [MyCustomObjects]())

// 重排操作
var tempArray = designerDress.value
tempArray.reorderAsperMywish()
designerDress.acceptSilently(tempArray)

方案三:临时取消订阅再重新订阅(不推荐)

这种方式需要先保存当前订阅,取消后更新值,再重新订阅,但存在竞态风险(更新期间可能丢失其他事件),仅作参考:

// 保存原订阅
var uiSubscription: Disposable? = designerDress
    .subscribe(onNext: { dresses in
        // 更新UI逻辑
    })
    .disposed(by: disposeBag)

// 取消订阅
uiSubscription?.dispose()

// 重排并更新
var tempArray = designerDress.value
tempArray.reorderAsperMywish()
designerDress.accept(tempArray)

// 重新订阅
uiSubscription = designerDress
    .subscribe(onNext: { dresses in
        // 更新UI逻辑
    })
    .disposed(by: disposeBag)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 15:17:50