2016-08-01 51 views
1

我正在从Firebase数据库加载数据。我正在尝试在用户滚动时加载数据。例如,如果他滚动了大约20 cells,那么我想多加载一下大约5 cells。我想实现像这样,但它不工作:在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() 

       } 
      } 
     }) 
    } 

,并检测多少个单元滚动:

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

       } 
      } 
     }) 
    } 
} 

这是我火力地堡结构:

enter image description here

有没有更好的解决方案,还是应该继续这样尝试?

Here你可以看到整个代码。我知道它缺乏OO,但我正在学习:)

回答

2

您可能想要使用offset来在您的应用中实现分页。

首先,在子路径中添加order键,可能是当前插入的时间戳,以便您可以对其进行排序并在分页中使用它。

例如,

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

现在,为了实现分页,你将检索21条记录,并在这些记录中,第一个20将记录在表格视图中使用,而最后一条记录将被用于检索接下来的offset记录集。

创建从firebase获取数据的函数:

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

而且从viewDidLoad调用此updateNewRecords方法,传递0检索前20条记录。

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

同样当用户滚动到下在table view,调用此方法,updateNewRecords路过的偏移量,以检索的20个记录下一个组。

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

您可以维护您的数据在firebase被修改更新表值的数组offsetArray

例如,假设某些数据在您的表中某处被修改,那么将调用observeEventType,您应该只从firebase中提取那些记录范围。你可以使用维护一个offsets的数组来实现它。所以当更新任何记录时,retrievePost将被调用从offsetArray。在正常情况下(在检索viewDidLoadscrollViewDidEndDragging的数据时),偏移量将为kOffset,在其余情况下(在侦听数据更改时),偏移量将从offsetArray

可以定义将返回offset值特定更新列的函数:

// 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] 

    } 

您还可以修改retrievePost方法,并传递一个额外的参数来检索特定数量的记录。

+0

你是什么意思kOffset和findOffsetFromArray。我必须创建另一个数组吗? –

+0

@TarvoMäesepp我已经添加了更多关于'offsetAray'和'kOffset'的解释。 – triandicAnt

+0

你的回答绝对好,我接受它,但我认为我不会继续。这太令人困惑:D没有更简单的方法来实现这一点吗?有没有任何工作的例子,你可能知道吗? –