Dwifft & ReactiveCocoa

Me encanta Dwifft pero me encantaría aún más utilizarlo con ReactiveCocoa para ayudar a networkingucir la complejidad del código en mis controlleres de vista de colección aún más.

Actualmente, tengo una class helper que toma una instancia de SignalProducer<[[T]]> donde T: Equatable (por lo que funciona con la diferencia). Cada vez que el productor de señales emite un nuevo valor:

  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() 

Aquí, al enumerar a través de mi matriz 2d, si todavía no existe una calculadora de diferencias, se crea una y se agrega a mi matriz de almacenamiento, diffCalculators . Si existe, se establece la propiedad de rows . Luego, recorro las secciones restantes y las elimino.

Desafortunadamente, he tenido un increíble fracaso en hacer que esto funcione. Una y otra vez obtengo 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).' y no puedo decir si eso está en mi lógica o si estoy usando Dwifft mal.

¿Alguna sugerencia?

Recompensa editada:

Como reference, he aquí la class auxiliar que he creado para vincular vistas de recostackción con datos de cocoa reactivos: https://gist.github.com/startupthekid/b3a69363d83e2279da0d750959c5a930

Lo que necesito es una forma de producir y modificar CollectionViewDiffCalculators de una manera reactiva y segura. Actualmente, el uso de los efectos secundarios se bloquea según la rapidez con que recibo nuevos datos (se está calculando un diff, los datos ingresan y la vista de recostackción intenta una recarga al mismo time).

Descubrí después de mucho juicio y tribulación que el problema no estaba realmente de mi parte, estaba dentro de las partes internas de Dwifft. Dwifft asume que las filas se establecerán una vez y, a partir de ahí, se insertán en o se eliminarán de ellas.

Pero cuando vincula una matriz con ReactiveCocoa, toda la matriz se sobrescribe cada vez que emite el productor de la señal, por lo que lo que termina sucediendo es hacer coincidir las inserciones y las eliminaciones se generarán para una única emisión. Luego, los elementos intentarán ser insertados y eliminados y de ahí provienen los fallos.

La forma de evitarlo es:

 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) } }) 

Esencialmente lo mismo que las partes internas de Dwifft, pero con las comprobaciones adicionales de if !Set(insertions).subtract(deletions).isEmpty { ... } .