2016-05-09 10 views
5

Amo Dwifft, ma mi piacerebbe molto di più usarlo con ReactiveCocoa per ridurre ulteriormente la complessità del codice nei miei controller di vista collezione.Dwifft & ReactiveCocoa

Attualmente, ho una classe di supporto che accetta un'istanza di SignalProducer<[[T]]> dove T: Equatable (quindi funziona con la differenza). Ogni volta che il produttore del segnale emette un nuovo valore:

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

Qui, durante l'enumerazione attraverso la mia matrice 2D, se un calcolatore diff non esiste ancora, si è creato e ha aggiunto al mio array di storage, diffCalculators. Se esiste, viene impostata la proprietà rows. Successivamente, eseguo il loop delle sezioni rimanenti e rimuoverle.

Sfortunatamente, sono stato incredibilmente infruttuoso nel farlo funzionare. Di volta in volta ottengo un numero 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).' e non riesco a capire se è nella mia logica o se sto usando Dwifft in modo errato.

Qualche suggerimento?

Bounty edit:

Per riferimento, ecco la classe di supporto che ho costruito per legare insieme viste di raccolta con reattiva dati cacao: https://gist.github.com/startupthekid/b3a69363d83e2279da0d750959c5a930

cosa ho bisogno è un modo per produrre e modificare CollectionViewDiffCalculators in un reattivo, al sicuro. Attualmente si verificano arresti anomali degli effetti collaterali a seconda di quanto rapidamente ricevo nuovi dati (viene calcolato un diff, i dati arrivano e la vista della raccolta tenta di ricaricarla contemporaneamente).

+0

Ciò si verifica a causa di un inserimento o eliminazione di incoerenza nella struttura dati che popola la vista raccolta. l'hai debugato? – Harris

+0

Sì, l'ho fatto, il problema non era nella mia struttura dati, posterò una risposta e spiegherò cosa stava succedendo. – barndog

risposta

1

Ho scoperto dopo molte prove e tribolazioni che il problema non era in realtà dalla mia parte, era all'interno degli interni di Dwifft. Dwifft fa in modo che le righe vengano impostate una volta e da lì in poi, inserite o rimosse da.

Tuttavia, quando si associa un array a ReactiveCocoa, l'intero array viene sovrascritto ogni volta che il produttore del segnale emette, quindi ciò che succede è la corrispondenza degli inserimenti e delle eliminazioni per una singola emissione. Gli articoli tenteranno quindi di essere inseriti ed eliminati e da lì provengono gli arresti anomali.

Il modo per aggirare questo è:

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

Essenzialmente lo stesso come la struttura interna di Dwifft ma con i controlli aggiunti di if !Set(insertions).subtract(deletions).isEmpty { ... }.

Problemi correlati