Dwift & ReactiveCocoa

Posted

技术标签:

【中文标题】Dwift & ReactiveCocoa【英文标题】:Dwifft & ReactiveCocoa 【发布时间】:2016-05-09 23:06:40 【问题描述】:

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

目前,我有一个辅助类,它采用 SignalProducer<[[T]]> 的实例,其中 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。如果确实存在,则设置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).',但我不知道这是我的逻辑还是我使用 Dwift 错误。

有什么建议吗?

赏金编辑:

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

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

【问题讨论】:

这是由于填充集合视图的数据结构中的插入或删除不一致而发生的。你调试了吗? 是的,我做到了,问题不在我的数据结构中,我会发布答案并解释发生了什么。 【参考方案1】:

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

但是,当您使用 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)
            
        )

与 Dwift 的内部结构基本相同,但增加了 if !Set(insertions).subtract(deletions).isEmpty ... 的检查。

【讨论】:

以上是关于Dwift & ReactiveCocoa的主要内容,如果未能解决你的问题,请参考以下文章

ReactiveCocoa

最快让你上手ReactiveCocoa之基础篇(简称RAC)

最快让你上手ReactiveCocoa之基础篇

最快让你上手ReactiveCocoa之基础篇

ReactiveCocoa基础篇

使用 carthage 集成 ReactiveCocoa 失败