Dwifft&ReactiveCocoa

bar*_*dog 5 ios reactive-cocoa swift

我喜欢Dwifft,但我更希望将它与ReactiveCocoa一起使用,以帮助减少我的集合视图控制器中的代码复杂性.

目前,我有一个辅助类,它接受SignalProducer<[[T]]>where 的实例T: Equatable(因此它适用于不同的).每次信号产生器发出一个新值:

    self.data.producer.observeOn(UIScheduler()).on(next: { [unowned self] in
        guard let collectionView = self.collectionView else { return }
        for (index, element) in $0.enumerate() {
            if index == self.diffCalculators.count {
                let calculator = CollectionViewDiffCalculator<T>(collectionView: collectionView, initialRows: element)
                calculator.sectionIndex = index
                self.diffCalculators.append(calculator)
            } else {
                let calculator = self.diffCalculators[index]
                calculator.rows = element
            }
            for index in self.data.value.count..<(self.diffCalculators.count >= self.data.value.count ? self.diffCalculators.count : self.data.value.count) {
                self.diffCalculators.removeAtIndex(index)
            }
        }
    })
        .takeUntil(self.willDeallocSignal())
        .start()
Run Code Online (Sandbox Code Playgroud)

在这里,通过我的2d数组枚举,如果还没有存在差异计算器,则会创建一个并添加到我的存储阵列中diffCalculators.如果确实存在,rows则设置该属性.之后,我遍历其余部分并将其删除.

不幸的是,我一直难以置信地将其付诸实践.一次The number of sections contained in the collection view after the update (1) must be equal to the number of sections contained in the collection view before the update (0), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted).'又一次,我得到一个,我不知道这是在我的逻辑或我是否使用Dwifft错误.

有什么建议?

赏金编辑:

作为参考,这里是我用于将集合视图与反应性可可数据绑定在一起的助手类:https://gist.github.com/startupthekid/b3a69363d83e2279da0d750959c5a930

我需要的是一种以CollectionViewDiffCalculators反应性,线程安全的方式生成和修改的方法.目前使用副作用崩溃取决于我接收新数据的速度(计算一个差异,数据进入,并且集合视图同时尝试重新加载).

bar*_*dog 1

经过多次尝试和磨难后,我发现问题实际上并不在我这边,而是在 Dwifft 的内部。Dwifft 假设行将被设置一次,然后从那里插入或删除。

但是,当您将数组与 ReactiveCocoa 绑定时,每次信号生成器发出时整个数组都会被覆盖,因此最终发生的情况是为单次发出生成匹配的插入和删除。然后,项目将尝试插入和删除,这就是崩溃的根源。

解决这个问题的方法是:

self.diffs <~ self.data.producer.combinePrevious([])
        .map { Zip2Sequence($0.0, $0.1) }
        .map { $0.map { $0.0.diff($0.1) } }
        .on(next: { [weak self] in
            let changes = $0.enumerate().map { index, diff in (diff.insertions.map({ NSIndexPath(forItem: $0.index, inSection: index) }), diff.deletions.map({ NSIndexPath(forItem: $0.index, inSection: index) })) }
            let insertions = changes.map { $0.0 }.flatMap { $0 }
            let deletions = changes.map { $0.1 }.flatMap { $0 }
            if !Set(insertions).subtract(deletions).isEmpty {
                self?.collectionView?.performBatchUpdates({
                    if !insertions.isEmpty { self?.collectionView?.insertItemsAtIndexPaths(insertions) }
                    if !deletions.isEmpty { self?.collectionView?.deleteItemsAtIndexPaths(deletions) }
                }, completion: nil)
            }
        })
Run Code Online (Sandbox Code Playgroud)

本质上与 Dwifft 的内部结构相同,但增加了if !Set(insertions).subtract(deletions).isEmpty { ... }.