Dwifft& ReactiveCocoa

时间:2016-05-09 23:06:41

标签: ios swift reactive-cocoa

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

目前,我有一个帮助器类,其中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() (所以它适用于不同的)。每次信号产生器发出新值时:

diffCalculators

这里,在枚举我的2d数组时,如果还没有存在差异计算器,则会创建一个并将其添加到我的存储阵列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).'属性。之后,我遍历其余部分并将其删除。

不幸的是,我一直难以置信地将其付诸实践。我一次又一次得到CollectionViewDiffCalculators,我无法判断这是否属于我的逻辑,或者我是否使用了Dwifft错误。

有什么建议吗?

Bounty编辑:

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

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

1 个答案:

答案 0 :(得分: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)
            }
        })

基本上与Dwifft的内部相同,但增加了if !Set(insertions).subtract(deletions).isEmpty { ... }的检查。