如何阻止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
相关产品推荐
相关产品推荐

