【问题标题】:Retrieve only 5 users at a time :Firebase [like Instagram]一次只检索 5 个用户:Firebase [如 Instagram]
【发布时间】:2017-01-18 17:30:11
【问题描述】:

在过去的几天里,我一直在尝试为我的应用创建类似 Instagram 的提要。更具体地说:每次用户从底部更新提要时加载新帖子 (5)。

我目前正在使用 Firebase 来存储和显示我的数据。

到目前为止,我的代码如下所示:

    var ref:FIRDatabaseReference!

    var dict = [String:Any]()
    var posts = [[String:Any]]()

   override func viewDidLoad() {
        super.viewDidLoad()

        tableView.delegate = self
        tableView.dataSource = self

        ref = FIRDatabase.database().reference()

        // Do any additional setup after loading the view, typically from a nib.
    }

    override func viewDidAppear(animated: Bool) {

        loadValues()

    }

    func loadValues() {

        dict.removeAll()
        posts.removeAll()


        ref.child("posts").queryOrderedByChild("timeCreated").queryLimitedToLast(5).observeEventType(.ChildAdded) { (snapshot:FIRDataSnapshot) in

            if let timeCreated = snapshot.value!["timeCreated"] as? Int {
                self.dict["timeCreated"] = timeCreated
            }

            if let postText = snapshot.value!["postText"] as? String {
                self.dict["postText"] = postText
            }


            self.posts.append(self.dict)


            self.tableView.reloadData()

        }




    }


    func scrollViewDidScroll(scrollView: UIScrollView) {

        if (scrollView.contentOffset.y + scrollView.frame.size.height) >= scrollView.contentSize.height {

            //tableView.tableFooterView!.hidden = true
            let pagingSpinner = UIActivityIndicatorView(activityIndicatorStyle: .Gray)
            pagingSpinner.startAnimating()
            pagingSpinner.hidesWhenStopped = true
            pagingSpinner.sizeToFit()
            tableView.tableFooterView = pagingSpinner

            //loadMore(5)

        } else {

            let pagingSpinner = UIActivityIndicatorView(activityIndicatorStyle: .Gray)
            pagingSpinner.stopAnimating()
            pagingSpinner.hidesWhenStopped = true
            pagingSpinner.sizeToFit()
            pagingSpinner.hidden = true
            tableView.tableFooterView = pagingSpinner
            tableView.tableFooterView?.hidden = true


        }


    }


    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return posts.count

    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)

        if let postText = posts[indexPath.row]["postText"] as? String {
            cell.textLabel!.text = postText
        }

        return cell

    }

    func loadMore(increment:Int) {

        //What should go in here?

    }

所以我在这里尝试做的是检测用户何时滚动到底部(在我的 scrollViewDidScroll 函数中。然后我正在简单地显示活动指示器,并调用函数 loadMore(5) where 5是我想要显示的新帖子的数量。

所以这里我有两个问题。 timeCreated 变量只是一个时间戳,我有十条记录(1-10,其中 10 是最新的,1 是最旧的)。使用我现在拥有的这段代码,tableView 以升序视图显示数据,从 5 开始到 10 结束。

我试图通过在 loadValues 函数中附加字典之前简单地执行 .reverse() 来反转字典数组(post)。因为我只是希望它在顶部显示 10,在底部显示 5。

我遇到的第二个问题是,我似乎真的找不到更新 tableView 的好方法(添加另外 5 条记录)。我试图简单地只拥有一个默认值为 5 的全局变量,然后在 loadMore 上简单地将其加 5,然后在 dict 和帖子上执行 removeAll() - 没有运气(tableView 滚动到顶,我不想)。我还尝试同时使用 queryLimitedTolast 和 queryLimitedToFirst,最终复制了一些数据。

因此,换句话说,我还需要检查用户实际上是否可以加载 5 个新的唯一帖子(或者例如 3,如果只剩下 3 个唯一帖子)。

有人对我将如何处理这个问题有任何想法吗?

非常感谢您的帮助,因为过去两天我一直在努力解决这个问题。

【问题讨论】:

标签: swift uitableview firebase firebase-realtime-database updates


【解决方案1】:

如果您使用tableView,请更新您的DataSource,而不是在特定索引处添加一行。使用struct 是一种常见的方法。

struct dataS {

var postData : String!
var index_Initial : Int!

init(post : String!, ind : Int!)
{
 self.postData = post
 self.index_Initial = ind
  }

}
  • 声明一个 dataSourceS

    类型的数组
         var dataFeed= [dataS]()
    
  • 要知道您已经检索了多少帖子,您需要将每个帖子的索引保留在 post 节点本身中。这可以通过计算 post 节点中的子节点数量并递增来完成它由一个。或创建一个完整的单独节点

    noOfPosts: 100, //Lets say there are 100 posts in your DB 
    
     Posts : {
      Post1:{
    
    
         text : asdasdasd,
         index : 12               
    
          },
    
       Post2:{
    
    
         text : asdasddasdasd,
         index : 13              
    
          },.....
     }
    

您的最终代码将如下所示:-

 import UIKit
import Firebase

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

var dataFeed = [dataS]()
let pagingSpinner = UIActivityIndicatorView(activityIndicatorStyle: .Gray)
var totalNoOfPost : Int!



@IBOutlet weak var customTableView: UITableView!




override func viewDidLoad() {
    super.viewDidLoad()

    customTableView.delegate = self
    customTableView.dataSource = self
}

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    FIRDatabase.database().reference().child("Posts").observeSingleEventOfType(.Value, withBlock: {(snap) in

        if let postDict = snap.value as? [String:AnyObject]{

             self.totalNoOfPost = postDict.count

                self.loadMore()
        }
    })

}

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return dataFeed.count
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = customTableView.dequeueReusableCellWithIdentifier("customCell") as! customTableViewCell
    if dataFeed.count > 0{
    cell.poatLabel.text = dataFeed[indexPath.row].postData
    }
    return cell
}

func loadMore(){

    let initialFeedCount : Int = dataFeed.count

    if totalNoOfPost - initialFeedCount - 4 > 0{

    FIRDatabase.database().reference().child("Posts").queryOrderedByChild("index").queryStartingAtValue(totalNoOfPost - initialFeedCount - 4).queryEndingAtValue(totalNoOfPost - initialFeedCount).observeEventType(.Value, withBlock: {(recievedSnap) in

        if recievedSnap.exists(){

        for each in recievedSnap.value as! [String:AnyObject]{
            let temp = dataS.init(post: each.1["text"] as! String, ind : each.1["index"] as! Int)
            self.dataFeed.insert(temp, atIndex: 5 * Int(self.dataFeed.count/5))
            self.dataFeed.sortInPlace({$0.index_Initial > $1.index_Initial})
               if self.dataFeed.count == initialFeedCount+5{
                self.dataFeed.sortInPlace({$0.index_Initial > $1.index_Initial})
                self.customTableView.reloadData()

            }
          }

         }
        }, withCancelBlock: {(err) in

            print(err.localizedDescription)


      })

    }else if totalNoOfPost - initialFeedCount - 4 <= 0{


        FIRDatabase.database().reference().child("Posts").queryOrderedByChild("index").queryStartingAtValue(0).queryEndingAtValue(totalNoOfPost - initialFeedCount).observeEventType(.Value, withBlock: {(recievedSnap) in

            if recievedSnap.exists(){

            for each in recievedSnap.value as! [String:AnyObject]{

                let temp = dataS.init(post: each.1["text"] as! String, ind : each.1["index"] as! Int)

                self.dataFeed.insert(temp, atIndex: 5 * Int(self.dataFeed.count/5))
                self.dataFeed.sortInPlace({$0.index_Initial > $1.index_Initial})
                if self.dataFeed.count == initialFeedCount+4{
                   self.dataFeed.sortInPlace({$0.index_Initial > $1.index_Initial})
                    self.customTableView.reloadData()
                        self.pagingSpinner.stopAnimating()
                }
              }
            }else{

            self.pagingSpinner.stopAnimating()
            }

            }, withCancelBlock: {(err) in

                print(err.localizedDescription)


        })
    }
}

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    if (indexPath.row + 1) == dataFeed.count {
        print("Displayed the last row!")


                    pagingSpinner.startAnimating()
                    pagingSpinner.hidesWhenStopped = true
                    pagingSpinner.sizeToFit()
                    customTableView.tableFooterView = pagingSpinner
                    loadMore()
    }
}


}


struct dataS {

var postData : String!
var index_Initial : Int!

init(post : String!, ind : Int!)
{
 self.postData = post
 self.index_Initial = ind
  }

}

【讨论】:

  • 您的代码确实对我有很大帮助,但是当孩子被改变时,您如何处理这种情况?假设来自节点的postData 被更改,然后代码因为observeEventType 而被召回。我试图在我的控制器中使用你的代码。但它有,例如一个孩子,喜欢。一旦添加了新的赞,loadMore 的代码就会再次触发,并且帖子会被多次添加。在我使用myPostArray.removeAll() 之前,我将如何使用您的方法处理它?
  • 也。 “索引”事物如何处理用户可能删除 1 或 2 个帖子的情况?那么我们的索引会有差距吗?这将如何影响进一步的负载?
  • 为了在您的 post 系统中进行有效索引,您必须在数据库中添加一个单独的节点,该节点由 active_Indexes 在执行相应操作时,您将从该节点附加/删除索引号。现在只需选择活动的 5 索引号,搜索它们并检索和更新您的 UI。现在实际的事情会比这复杂得多,但你必须脑筋急转弯......这实际上是一个相当复杂的情况......但我已经向你展示了从哪里开始......根据你的操作需要
  • 基本思想是保留一个单独的节点,该节点承载活动索引,您可以从中过滤和搜索
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-16
  • 2017-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多