2016-08-01 12 views
1

Ich lade Daten aus der Firebase-Datenbank. Ich versuche Daten zu laden, während der Benutzer scrollt. Zum Beispiel, wenn er über 20 cells gescrollt hat, dann möchte ich etwas mehr über 5 cells laden. Ich versuche, es so zu erreichen, aber es funktioniert nicht:Paginierung beim Scrollen in Swift Firebase

func parseSnusBrands(){ 
     let ref = FIRDatabase.database().reference().child("Snuses").child("Brands") 

     ref.queryOrderedByKey().queryLimitedToLast(20).observeEventType(.Value, withBlock: { (snapshot) in 
      if snapshot.exists() { 
       if let all = (snapshot.value?.allKeys)! as? [String]{ 
        self.snusBrandsArray = all 
        self.snusBrandsTableView.reloadData() 

       } 
      } 
     }) 
    } 

und zu erkennen, wie viele Zellen gescrollt werden:

override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { 
    if indexPath.row == 20 { 
     let ref = FIRDatabase.database().reference().child("Snuses").child("Brands") 

     ref.queryOrderedByKey().queryLimitedToLast(20).observeEventType(.Value, withBlock: { (snapshot) in 
      if snapshot.exists() { 
       if let all = (snapshot.value?.allKeys)! as? [String]{ 
        self.snusBrandsArray = all 
        self.snusBrandsTableView.reloadData() 

       } 
      } 
     }) 
    } 
} 

Das ist meine Firebase Struktur:

enter image description here

Gibt es eine bessere Lösung oder sollte ich so weiter versuchen?

Here Sie können den gesamten Code sehen. Ich weiß, dass es an OO fehlt, aber ich lerne :)

Antwort

2

Sie können offset verwenden, um Paginierung in Ihrer App zu erreichen.

Fügen Sie zuerst einen order Schlüssel in Ihrem untergeordneten Pfad hinzu, kann der aktuelle Zeitstempel des Einfügens sein, damit Sie ihn bestellen und in Paginierung verwenden können.

Für z.

"brands": { 
     "catch" : { 
      ... 
      ... 
      "pOrder" : 555 
     }, 
     "etan" : { 
      ... 
      ... 
      "pOrder" : 444 
     }, 
     "general" : { 
      ... 
      ... 
      "pOrder" : 555 
     }. 
     ..... 
     } 

Jetzt Paginierung erreichen Sie 21 Datensätze und in die Datensätze abrufen würde, wird die ersten 20 Datensätze werden in der Tabellenansicht zu verwenden, während der letzte Datensatz der offset sein wird, der verwendet wird neben abrufen Satz von Datensätzen.

eine Funktion erstellen, die Daten aus firebase holt:

// MARK: Retrieving Data: Firebase 
    /* 
    retrieve current set of posts sorted by updated time of posts 
    */ 
    func retrievePost(offset: NSNumber, callFlag: Bool, completion: (result: AnyObject?, error: NSError?)->()){ 
     // As this method is called from viewDidLoad and fetches 20 records at first. 
     // Later when user scrolls down to bottom, its called again 
     let postsRef = ref.child(kDBPostRef) 
     var startingValue:AnyObject? 
     // starting value will be nil when this method is called from viewDidLoad as the offset is not set 

     if callFlag{ 
      if offset == 0{ 
       startingValue = nil 
      } 
      else{ 
       startingValue = offset 
      } 
     } else{ 
      // get offset from the offsetArray 
      startingValue = self.findOffsetFromArray() 

     } 
     // sort records by pOrder fetch offset+1 records 
     self.refHandler = postsRef.queryOrderedByChild("pOrder").queryStartingAtValue(startingValue).queryLimitedToFirst(kPostLimit + 1).observeEventType(FIRDataEventType.Value, withBlock: { (snapshot) in 
      // flag is for setting the last record/ 21st as offset 
      var flag = 0 

      let tempPost = NSMutableSet() 
       // iterate over children and add to tempPost 
       for item in snapshot.children { 

        // check for offet, the last row(21st) is offset ; Do not add last element in the main table list 
        flag += 1 
        if flag == 21 && callFlag == true{ 
         // this row is offset 
         self.kOffset = item.value?["pOrder"] as! NSNumber 
         self.offSetArray?.append(self.kOffset) 
         continue 
        } 
        // create Post object 
        let post = Post(snapshot: item as! FIRDataSnapshot) 

        // append to tempPost 
        tempPost.addObject(post) 
       } 
       // return to the closure 
       completion(result:tempPost, error:nil) 
     }) 
    } 

Und nennen diese updateNewRecords Methode von viewDidLoad, 0 ersten 20 Datensätze abzurufen vorbei.

func updateNewRecords(offset:NSNumber, callFlag: Bool){ 
     self.retrievePost(offset,callFlag:callFlag) { (result,error) -> Void in 
//   let tempArray = result as! [Post] 
      let oldSet = Set(self.posts) 
      var unionSet = oldSet.union(result as! Set<Post>) 
      unionSet = unionSet.union(unionSet) 
      self.posts = Array(unionSet) 
      self.postsCopy = self.posts 
//   print(self.posts.count) 
      self.posts.sortInPlace({ $0.pOrder> $1.pOrder}) 
      self.reloadTableData() 
     } 
    } 

wieder, wenn der Benutzer einen Bildlauf nach unten in der table view, rufen diese Methode, updateNewRecords der Offset, Übergeben nächsten Satz von 20 Datensätzen abzurufen.

func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) { 

     // UITableView only moves in one direction, y axis 
     let currentOffset = scrollView.contentOffset.y 
     let maximumOffset = scrollView.contentSize.height - scrollView.frame.size.height 

     // Change 10.0 to adjust the distance from bottom 
     if maximumOffset - currentOffset <= 10.0 { 
      self.updateNewRecords(self.kOffset, callFlag:true) 
     } 
    } 

Sie können ein Array offsetArray zum Aktualisieren von Tabellenwerten halten, wenn Sie Ihre Daten in firebase geändert wird.

Für z.B. Angenommen, einige Daten werden irgendwo in Ihrer Tabelle geändert, in diesem Fall wird observeEventType aufgerufen und Sie sollten nur diesen Datensatzbereich von firebase abrufen. Sie können dies unter Verwendung eines Arrays von offsets erreichen. Wenn also ein Datensatz aktualisiert wird, wird der retrievePost mit dem entsprechenden offset von offsetArray aufgerufen. Im Normalfall (beim Abrufen von Daten von viewDidLoad und scrollViewDidEndDragging) ist der Offset kOffset und in den restlichen Fällen (während der Datenänderung) wird der Offset von offsetArray sein.

Sie können eine Funktion definieren, die den offset Wert für eine bestimmte aktualisierte Spalte zurück:

// find the offset from the offsetDict 
    func findOffsetFromArray() -> NSNumber{ 
     let idx = self.kClickedRow/20 // kClickedRow is the updated row in the table view 
     return self.offSetArray![idx] 

    } 

Sie können auch retrievePost Methode ändern und einen zusätzlichen Parameter übergeben, eine bestimmte Anzahl von Datensätzen abzurufen.

+0

Was meinen Sie mit kOffset und findOffsetFromArray. Muss ich ein anderes Array erstellen? –

+0

@ TarvoMäsepp Ich habe weitere Erklärungen über die 'offsetAray' und' kOffset' hinzugefügt. – triandicAnt

+0

Ihre Antwort ist absolut gut und ich akzeptiere sie, aber ich denke, ich gehe nicht weiter damit. Es ist zu verwirrend: D Gibt es keinen einfacheren Weg, dies zu erreichen? Gibt es vielleicht ein funktionierendes Beispiel? –