json - 在 Swift Firebase 中滚动时分页

标签 json swift uitableview firebase firebase-realtime-database

我正在从 Firebase 数据库加载数据。我正在尝试在用户滚动时加载数据。例如,如果他滚动了大约 20 个 cells,那么我想再加载大约 5 个 cells。我正在尝试像这样实现它,但它不起作用:

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

                }
            }
        })
    }
}

这是我的 Firebase 结构:

enter image description here

是否有更好的解决方案或者我应该继续这样尝试?

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

最佳答案

您可能希望使用 offset 在您的应用中实现分页。

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

例如。

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

现在,要实现分页,您将检索 21 条记录,在这些记录中,前 20 条将是要在 TableView 中使用的记录,而最后一条记录将是将要使用的 偏移量检索下一组记录。

创建一个从 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()
        }
    }

再次当用户滚动到 TableView 底部时,调用此方法,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 数组来实现它。因此,当任何记录更新时,将使用 offsetArray 中相应的 offset 调用 retrievePost。在正常情况下,(从 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 方法并传递一个额外的参数来检索一定数量的记录。

关于json - 在 Swift Firebase 中滚动时分页,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38705925/

相关文章:

java - 从 JSON 文件中获取数据,保存为对象并使用键值获取数据

ios - 在 ios 中调用嵌套的 json 对象

ios - swift : Delete PFUser in Parse From a TableView

iphone - 具有多个手势的 UITableViewCell : long-press and tap

ios - 管理 Swift 表格 View 中的部分

ios - UITableViewCell 滚动自定义 UITableView 标题标题

javascript - 使用 KnockoutJS 将 JSON 对象映射到 View 模型的一部分

javascript - 通过 Zapier 代码发布到 Webhooks

swift - 将 scenekit 和 spritekit 组合在一个屏幕中

objective-c - 带有分页的全屏 UICollectionView 内的 UIWebView