ios - 防止 RxSwift 中的冗余操作

标签 ios swift reactive-programming rx-swift rx-cocoa

我正在开始使用 RxSwift 的冒险,在 js 中已经有一些 React 的经验。我认为我的问题很常见,但我不确定如何以简洁抽象的方式描述它,所以我将在示例中描述它。

我正在构建显示一些图表的 iOS 应用程序。感兴趣的部分包括 ChartAreaController、ChartInfoController,它们都嵌入在 ChartController 中。第一个 Controller 是显示一些图形的区域(基于 rx chartData 属性),第二个 Controller 将有一个 slider 供用户限制显示 x 值(rx selectedXRange 属性),该值被限制在一些最小值和最大值之间。最小/最大值由当前图表数据定义。

在 ChartController 中定义 slider 更改更新图表时的行为:

override func viewDidLoad() {
   super.viewDidLoad()
   (...)
   chartInfoController.selectedXRange.asObservable()
                .subscribe(onNext: { [unowned self] selectedXRange in
                    (...)
                    let chartData = self.filterChartData(from: self.rawChartData, in: selectedXRange)
                    self.chartAreaController.chartData.accept(chartData)
                }).disposed(by: disposeBag)

filterChartData() 方法只是过滤掉不在范围内的数据,但为了论证我们可以假设它非常昂贵,我不希望它在不必要时运行两次。

当用户更改他或她想要显示的图表时,新数据从服务器(同样是 ChartController)到达:

private func handleNewData(_ rawChartData: ChartData) {
        self.rawChartData = rawChartData

        guard let allowedXRange = rawChartData.xRange() else { return }
        let selectedXRange = chartInfoController.selectedXRange.value
        let newSelectedXRange = calculateSelectedXRange(currentSelectedDays: selectedDaysRange, availableDaysRange: daysRange)
        let chartData = filterChartData(from: rawChartData, in: selectedXRange)

        self.chartInfoController.allowedXRange = allowedXRange //this line is not crucial
        self.chartInfoController.selectedXRange.accept(newSelectedXRange)

        self.chartAreaController.chartData.accept(rawChartData)
    }

因此,在新图表数据到达时,由于数据的新最小/最大值,可能必须修整当前选择的 xRange。因此,该方法的副作用是更改 selectedXRange,进而运行我之前粘贴的订阅。因此,当新数据到达时,chartData 会更新两次,我不希望它发生。

当然我可以注释掉 handleNewData() 方法的最后一行,但我不太喜欢它,因为 handleNewData() 存在的主要原因是设置 chartData,并且注释掉它的行由于该方法的副作用(正在更新 slider ),目标将得以实现。 Not Acceptable 。

我还是为 chartData 添加了 throttle ,因为快速移动的 slider 会导致很多更新,这部分解决了我的问题(chartData 只更新了一次)。但是您可能还记得 filterChartData() 方法的开销很大,而且这部分仍将运行两次。

所以唯一的问题是,如果我解决问题的总体布局没问题,还是应该以不同的方式处理?在这一点上,我得出结论,我正在寻找某种方法来临时禁用 selectedXRange 上的特定订阅(而不破坏对该变量的其他订阅)。暂定意义:

(...)
//disable subscription
self.chartInfoController.selectedXRange.accept(newSelectedXRange)
self.chartAreaController.chartData.accept(rawChartData)
//enable subscription
(...)

这对我来说似乎是合法的,因为 ChartController 作为订阅的所有者和值的更改者可能希望在适合他(它?)的时候禁用订阅。

RxSwift 支持这样的东西吗?如果没有,那么我想我可以自己实现它,例如通过 ChartController 中的 bool 属性,或通过将订阅添加到单独的 disposeBag,我将处理它然后重新创建订阅。但如果这样做是件好事呢?例如,当出现某些错误时,bool 解决方案可能容易被错误处理,并且处置/重新创建可能会以某种方式代价高昂,并且可能是处置不打算像那样使用的情况。

有没有更好的做法来处理这种情况?正如我所说,我认为这个问题很常见,所以我希望有一个规范的解决方案:)感谢您的任何回答,对于冗长的帖子感到抱歉。

最佳答案

So the one question is, if my general layout of tackling the problem is OK, or should it be handled way different?

正确编写的 UI 输入元素 observable 只会在用户对 UI 进行更改时触发,而不是在程序进行更改时触发。例如: textField.rx.text.orEmpty.subscribe(onNext: { print($0) }) 只会在用户在 textField 中键入时打印一个值,而不是在您调用 textField.text = “foo” 或来自绑定(bind) .bind(to: textfield.rx.text)

如果您编写了 ChartInfoController,我建议您修改它以使其像其他 UI 元素一样工作。如果不是您编写的,请向开发人员/维护人员提交问题。

Does RxSwift support something like [temporarily disabling particular subscription]?

这取决于您所说的“暂时禁用”是什么意思。它不支持静默取消订阅和重新订阅,但有很多运算符(operator)会过滤掉他们收到的一些事件,同时传递其他事件。例如 filterthrottledebounceignoreElements……有很多这样做的。

Is there a better practice to handle such situations?

那么最佳方案就是上面提到的。

关于ios - 防止 RxSwift 中的冗余操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61520752/

相关文章:

ios - 在两个设备之间发送时数据会被弄乱

ios - 自定义UITableViewCell是否需要使用reuseIdentifier注册?

Swift 4 - 垂直 UICollectionView 上的 UIRefreshControl 滞后

swift - 计算属性中的基础变量 | swift

reactive-programming - 响应式流中的 Mono vs Flux

ios - 用户界面图像 : How to get website tab icon

ios - UIView 工厂和委托(delegate)

java - Rx java将无限流分成组并对每个组单独进行去抖

ios - 确定对象是否被触摸/轻敲

ios - 当且仅当 producerA 不抛出错误时如何执行 producerB?