2016-08-04 4 views
1

Um Elemente in einer UICollectionView zu verschieben, verwende ich einen UILongPressGestureRecognizer.UICollectionView-Zellen werden beim Verschieben nicht korrekt zwischen den Abschnitten verschoben

Ich implementiert die folgende Geste Handler:

func handleLongGesture(gesture: UILongPressGestureRecognizer) { 
    switch(gesture.state) { 
    case UIGestureRecognizerState.Began: 
     guard let selectedIndexPath = self.collectionView.indexPathForItemAtPoint(gesture.locationInView(self.collectionView)) else {break} 
     collectionView.beginInteractiveMovementForItemAtIndexPath(selectedIndexPath) 
    case UIGestureRecognizerState.Changed: 
     collectionView.updateInteractiveMovementTargetPosition(gesture.locationInView(gesture.view!)) 
    case UIGestureRecognizerState.Ended: 
     collectionView.endInteractiveMovement() 
    default: 
     collectionView.cancelInteractiveMovement() 
    } 
} 

Zusammen mit einer korrekten Überschreibung der Delegierten Sammlung Ansicht Methode moveItemAtIndexPath arbeitet Zellen innerhalb eines Abschnitts bewegen perfekt. Darüber hinaus funktioniert das Verschieben von Zellen in andere sichtbare Abschnitte auch wie erwartet. Jedoch treten Probleme auf, wenn Zellen auf die Abschnitte zu bewegen, die durch Schwenken/Scrollen nach unten sichtbar werden, was zu dem folgenden Fehler (ich benutze eine Realm-Datenbank):

'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of items in section 0. The number of items contained in an existing section after the update (1) must be equal to the number of items contained in that section before the update (0), plus or minus the number of items inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of items moved into or out of that section (0 moved in, 0 moved out).' 

Das Problem an der Verfolgung von Standortänderungen im Zusammenhang scheint durch die Gestenerkenner in updateInteractiveMovementTargetPosition seit der Fehler bei dieser Methode auftritt.

Ich nehme an, dass updateInteractiveMovementTargetPosition die Sammlungsansichtsmethode moveItemAtIndexPath (nicht über den Delegaten) direkt aufruft, was zu einem Fehler führt, da Zwischenzellenstandortänderungen nicht in der Realm-Datenbank aktualisiert werden. Oder bin ich falsch?

Würde jemand wissen, warum das Verschieben zwischen Abschnitten für sichtbare Abschnitte funktioniert, aber nicht während des Schwenkens? Und wie sollte das Scrollen/Schwenken richtig gehandhabt werden?

Antwort

0

UICollectionView & UITableView-APIs sind sehr unversöhnlich, wenn es darum geht, Aktualisierungen im UI-Status vorzunehmen und diese in der Datenquelle zu spiegeln.

Sie müssen den Bereich aktualisieren, um den UI-Status zu reflektieren, damit UICollectionView glücklich bleibt.

Hier ist ein Beispiel für einen Realm-backed UITableViewController mit Reorderable Zellen, die Sie für Ihren UICollectionView Anwendungsfall anpassen konnten:

import UIKit 
import RealmSwift 

class ObjectList: Object { 
    let list = List<DemoObject>() 
} 

class DemoObject: Object { 
    dynamic var title = "" 
} 

class TableViewController: UITableViewController { 
    var items: List<DemoObject>? 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell") 
     tableView.editing = true 

     let realm = try! Realm() 
     if realm.isEmpty { 
      try! realm.write { 
       let list = ObjectList() 
       list.list.appendContentsOf(["one", "two", "three"].map { 
        DemoObject(value: [$0]) 
       }) 
       realm.add(list) 
      } 
     } 
     items = realm.objects(ObjectList.self).first!.list 
    } 

    override func tableView(tableView: UITableView?, numberOfRowsInSection section: Int) -> Int { 
     return items?.count ?? 0 
    } 

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
     let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) 
     cell.textLabel?.text = items?[indexPath.row].title 
     return cell 
    } 

    override func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle { 
     return .None 
    } 

    override func tableView(tableView: UITableView, shouldIndentWhileEditingRowAtIndexPath indexPath: NSIndexPath) -> Bool { 
     return false 
    } 

    override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) { 
     guard let items = items else { return } 
     try! items.realm?.write { 
      let itemToMove = items[fromIndexPath.row] 
      items.removeAtIndex(fromIndexPath.row) 
      items.insert(itemToMove, atIndex: toIndexPath.row) 
     } 
    } 
} 
+0

Dies ist, was ich für eine Sammlung Ansicht grundsätzlich umgesetzt und funktioniert ohne Probleme im Fall eines einzelner Abschnitt (und in einer Tabellenansicht auch für mehrere Abschnitte mit einem passenden 'moveRowAtIndexPath'). Das Problem, auf das ich stoße, tritt nur auf, wenn ich eine sich bewegende Zelle über die letzte Zelle eines Abschnitts hinaus in eine Sammlungsansicht mit mehreren Abschnitten verschiebe (mit einem einzelnen Abschnitt tritt kein Fehler auf). Ich habe einen Code veröffentlicht, in dem dieser Fehler auf [github] reproduziert werden kann (https://github.com/Taco55/CollectionViewCellMoving). Könnte das ein Fehler in Swift sein oder aktualisiere ich die Datenbank falsch? Jede Hilfe wäre willkommen – Taco

Verwandte Themen