一次只检索 5 个用户:Firebase [像 Instagram]
Retrieve only 5 users at a time :Firebase [like Instagram]
在过去的几天里,我一直在尝试为我的应用程序创建一个类似 Instagram 的提要。更具体地说:每次用户从底部更新提要时加载新的 posts (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 函数中。然后我简单地显示 activity 指示器,并调用该函数loadMore(5) 其中 5 是我要显示的新 post 的数量。
所以这里我有两个问题。 timeCreated 变量只是一个时间戳,我有十条记录(1-10,其中 10 是最新的,1 是最旧的)。使用我现在拥有的代码,tableView 在升序视图中显示数据,从 5 开始到 10 结束。
我试图通过在 loadValues 函数中附加字典之前简单地执行 .reverse() 来反转字典数组 (post)。因为我只是希望它在顶部显示 10,在底部显示 5。
我遇到的第二个问题是,我似乎真的找不到更新 tableView 的好方法(添加另外 5 条记录)。我试图简单地拥有一个默认值为 5 的全局变量,然后在 loadMore 上简单地将它加 5,然后在 dict 和 posts 上执行 removeAll() - 没有运气( tableView 滚动到顶部,我不想这样做)。我还尝试同时使用 queryLimitedTolast 和 queryLimitedToFirst,最终我复制了一些数据。
所以换句话说,我还需要检查用户实际上是否可以加载 5 个新的唯一 post(或者前 3 个,如果只剩下 3 个唯一 post) .
有人知道我将如何处理这个问题吗?
非常感谢您的帮助,因为过去两天我一直在努力解决这个问题。
如果您正在使用 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
节点中保留每个 post 的索引 itself.Which 可以通过计算 post
节点中子节点的数量并将其递增 one.Or 创建一个完整的独立节点
来完成
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({[=13=].index_Initial > .index_Initial})
if self.dataFeed.count == initialFeedCount+5{
self.dataFeed.sortInPlace({[=13=].index_Initial > .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({[=13=].index_Initial > .index_Initial})
if self.dataFeed.count == initialFeedCount+4{
self.dataFeed.sortInPlace({[=13=].index_Initial > .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
}
}
在过去的几天里,我一直在尝试为我的应用程序创建一个类似 Instagram 的提要。更具体地说:每次用户从底部更新提要时加载新的 posts (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 函数中。然后我简单地显示 activity 指示器,并调用该函数loadMore(5) 其中 5 是我要显示的新 post 的数量。
所以这里我有两个问题。 timeCreated 变量只是一个时间戳,我有十条记录(1-10,其中 10 是最新的,1 是最旧的)。使用我现在拥有的代码,tableView 在升序视图中显示数据,从 5 开始到 10 结束。
我试图通过在 loadValues 函数中附加字典之前简单地执行 .reverse() 来反转字典数组 (post)。因为我只是希望它在顶部显示 10,在底部显示 5。
我遇到的第二个问题是,我似乎真的找不到更新 tableView 的好方法(添加另外 5 条记录)。我试图简单地拥有一个默认值为 5 的全局变量,然后在 loadMore 上简单地将它加 5,然后在 dict 和 posts 上执行 removeAll() - 没有运气( tableView 滚动到顶部,我不想这样做)。我还尝试同时使用 queryLimitedTolast 和 queryLimitedToFirst,最终我复制了一些数据。
所以换句话说,我还需要检查用户实际上是否可以加载 5 个新的唯一 post(或者前 3 个,如果只剩下 3 个唯一 post) .
有人知道我将如何处理这个问题吗?
非常感谢您的帮助,因为过去两天我一直在努力解决这个问题。
如果您正在使用 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
节点中保留每个 post 的索引 itself.Which 可以通过计算post
节点中子节点的数量并将其递增 one.Or 创建一个完整的独立节点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({[=13=].index_Initial > .index_Initial})
if self.dataFeed.count == initialFeedCount+5{
self.dataFeed.sortInPlace({[=13=].index_Initial > .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({[=13=].index_Initial > .index_Initial})
if self.dataFeed.count == initialFeedCount+4{
self.dataFeed.sortInPlace({[=13=].index_Initial > .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
}
}