2017-07-27 4 views
0

Ich habe eine UICollectionViewController, die als Feed dient, der Daten aus meiner Firebase-Datenbank abruft und anzeigt. Es ist der Root-View-Controller des Fensters, also ist es immer vorhanden. Mein Problem ist, dass jedes Mal, wenn der Controller angezeigt wird, alle untergeordneten Elemente des beobachteten Knotens zur Sammlungsansicht hinzugefügt werden. Am Anfang ist das in Ordnung, aber wenn ich den Controller verlasse und zurückkehre, werden alle gleichen Daten angehängt, wodurch Duplikate erzeugt werden. Hier einig Pseudo-Code, was meine Interaktion mit Firebase:Swift Firebase beobachten mit .childAdded Abrufen von doppelten Daten

class ViewController: UIViewController { 

    var children_query: DatabaseQuery! 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     self.children_query = Database.database().reference().child("children").queryOrdered(byChild: "timestamp").queryStarting(atValue: Date().timeIntervalSince1970) 
    } 

    override func viewWillAppear(_ animated: Bool) { 
     super.viewWillAppear(animated) 
     self.observeAddedChildren() 
    } 

    override func viewWillDisappear(_ animated: Bool) { 
     super.viewWillDisappear(animated) 
     self.children_query.removeAllObservers() 
    } 

    func observeAddedChildren() { 
     self.children_query.observe(.childAdded, with: { snapshot in 
      print(snapshot.value) 
     }) 
    } 

} 

In diesem Pseudo-Code, anstatt mit UI Umgang, habe ich einfach snapshot drucken, aber der Punkt bleibt. Alle Kinder werden jedes Mal gedruckt, wenn der Controller erscheint. Wie kann ich nur Daten abrufen, die nicht abgerufen wurden? Vielen Dank.

Antwort

0

Ich habe Firebase nicht verwendet, aber wenn Sie einen Block an die observe-Funktion übergeben, deutet nichts darauf hin, dass die Beobachtung stoppt, wenn die Ansicht verschwindet.

Also frage ich mich, ob observe mehrere Male anrufen ist das Problem. Haben Sie in ViewDidLoad einmal versucht, observe anzurufen?

Alternativ haben eine Eigenschaft zu erfassen, ob die Beobachtung gestartet wurde:

var observing: Bool = false 

func observeAddedChildren() { 
    if observing { 
     return false 
    } 

    self.children_query.observe(.childAdded, with: { snapshot in 
     print(snapshot.value) 
    }) 
    observing = true 
} 

Edit: hier ein paar mehr Möglichkeiten, ist, weil Sie vermutlich die snapshot Elemente zu einem Array oder einer anderen Sammlung hinzugefügt sind , dann liest Ihr UICollectionViewDataSource Zeug von diesem Array.

Also entweder:

  1. leer dieses Array innerhalb viewWillAppear und dann self.collectionView.reloadData() nennen, oder
  2. wenn Ihr snapshot Objekt eine eindeutige Kennung Eigenschaft hat, setzen diese dann in ein Array, und die dann beobachtet Block ignorieren Gegenstände es schon gesehen hat, bevor

So:

var snapshotIDs : [String] = Array<String>() 

func observeAddedChildren() { 
    self.children_query.observe(.childAdded, with: { snapshot in 
     if !snapshotIDs.contains(snapshot.uniqueID) { 
      print(snapshot.value) 
      snapshotIDs.append(snapshot.uniqueID) 
     } 
    }) 
} 
+0

Nun, ich rufe 'self.children_query.removeAllObservers()' in 'viewWillDisappear' auf und letztendlich möchte ich nicht weiter beobachten, wenn die Ansicht nicht sichtbar ist. Aber gute Idee; Ich könnte das Problem so beheben. –

+0

Ich verstehe es. Aber wenn Sie 'removeAllObservers' aufrufen, dann' observe', wenn die Ansicht wieder sichtbar wird, hat das, was Sie beobachten, keine Ahnung, dass Sie bereits einige Elemente zu Ihrer Sammlungsansicht hinzugefügt haben. Entweder (1) entferne alle Elemente aus deiner Sammlungsansicht in 'viewWillAppear', oder (2) _you_ muss verfolgen, welche Elemente bereits hinzugefügt wurden, vielleicht in einem Array, und sie ignorieren, wenn sie in deinem Beobachter wieder gesehen werden Block. – Matthew

+0

@ArchieGertsman siehe bearbeitete Antwort – Matthew

Verwandte Themen