ios - ReactiveSwift 一个信号订阅与多个信号订阅以及相关的内存开销

标签 ios swift rx-swift reactive-swift

我在一个应用程序组件中有一个简单的信号,它返回一个项目数组:

var itemsSignal: Signal<[Item], Never>

这些项目可能包含以表格 View 形式呈现在屏幕上的数据的更新。任务是将更新应用到屏幕上出现的单元格。

我能想到有两种可能的方法来实现这一点。该应用程序是用 MVVM 风格编写的,但我只是为了示例的目的。

第一种方法是在 View Controller 代码级别上订阅此信号一次,然后在 observeValues block 中检查我们收到的项目更新的位置使用一些 for 循环进行屏幕并更新相应单元格的状态。这样,我们将只有一个订阅,但在我看来,当我们基本上使用 View Controller 级别代码将更新从源传递到屏幕上的各个单元格时,这会引入不必要的代码耦合。

第二种方法是从每个单独的单元(在现实单元的 View 模型中)订阅此信号并应用一些过滤,如下所示:

disposables += COMPONENT.itemsSignal
    .flatten()
    .filter({ $0.itemId == itemId })
    .observeValues({ 
        ... 
    })

但这会创建多个订阅 - 每个单元对应一个订阅。

我实际上更喜欢第二种方法,因为在我看来,从设计的角度来看它更干净,因为它不会泄漏任何不必要的知识来查看 Controller 级别代码。无论何时在不同的屏幕上重复使用相同的单元格,这种 self 更新行为都将被继承并且开箱即用。

问题是,由于多个订阅,第二种方法的内存/CPU 成本要高出多少?在此项目中,我们使用 ReactiveSwift,但我认为这也与其他 Rx 库相关。

最佳答案

在 RxSwift 中,我们的 RxCocoa 库已经实现了您的第一个想法,并在 tableView 上执行了简单的 reloadData。

items
    .bind(to: tableView.rx.items) { (tableView, row, element) in
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!
        cell.textLabel?.text = "\(element) @ row \(row)"
        return cell
    }

或者您可以告诉库该单元格的类型,它会为您创建单元格:

items
    .bind(to: tableView.rx.items(cellIdentifier: "Cell", cellType: UITableViewCell.self)) { (row, element, cell) in
        cell.textLabel?.text = "\(element) @ row \(row)"
    }

我们还有一个您没有提到的选项。单一订阅,但更智能的数据源,能够根据传入序列元素的相等性添加和删除单个单元格。它位于一个名为 RxDataSources 的单独库中。

作为关于资源的基本问题的答案...我经常使用混合解决方案,其中有一个仅包含对象 ID 序列的 Observable;这是您的第一个想法,但它只负责项目的插入和删除。我将创建第二个由 [ID: Info] 组成的 Observable,每个当前存在的单元格都会订阅该 Observable。在创建/重用单元格时,它会获得一个 ID 并订阅第二个可观察值,并仅过滤掉它感兴趣的信息。在单元格的 prepareForReuse 中,它会取消订阅。

由于每个现有单元格只有一个订阅,因此实际上并没有那么多新订阅(取决于单元格的高度和表格 View 的高度)。我的应用程序通常有数千个订阅任何一次运行的订阅数量,因此通过这种“每单元格”方法添加的额外订阅数量甚至不明显。

关于ios - ReactiveSwift 一个信号订阅与多个信号订阅以及相关的内存开销,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65659620/

相关文章:

ios - 是否可以在 CAKeyFrameAnimation 之后更新按钮的位置?

ios - Storyboard "Main",但在使用 UITableViewController 时没有获得 UITableView

ios - 如何缓存来自 API 的响应以防止额外的调用?

Swift Firestore 检索数据

ios - 我想使用框架 UIViewController 作为项目类的父类(super class)协议(protocol)

ios - NWListener 取消后如何重新启动?

swift - 是否有一个 Observable 的首选类型而不需要在 Next 事件中有一个值?

swift - 如何在 Eureka SelectableSection 上进行适当的响应式(Reactive)扩展

swift - RxSwift Driver 值的变异

ios 7 应用程序外观中的底栏