如何在Firebase的iOS SDK上执行分页查询?
这是我的模特。
messagesRef = Firebase(url: "https://"+CONSTANTS.FirebaseDB+".firebaseio.com/messages/1:1000") messagesRef.queryLimitedToLast(5).observeEventType(FEventType.ChildAdded, withBlock: { (snapshot) in self.message_list.append(snapshot) // it works. }); });
我的代码有效 – 它获取最后5条消息(8-12)。
但是,如果我有一个函数查询接下来的5条消息(2-6)怎么办? 有一个开始和偏移。 我怎么查询这个?
messagesRef = Firebase(url: "https://"+CONSTANTS.FirebaseDB+".firebaseio.com/messages/1:1000")messagesRef .queryOrderedByKey() .queryStartingAtValue(5) .queryEndingAtValue(10) .observeEventType(FEventType.ChildAdded, withBlock: { (snapshot) in self.message_list.append(snapshot) });
这是一个在黑暗中的镜头,但它似乎应该基于这里的文档https://www.firebase.com/docs/ios-api/Classes/Firebase.html#//api/name/queryStartingAtValue :
花了太多时间我已经弄明白了,这就是解决方案。 这是Objective-C代码,您可以将其转换为swift。 调用以下function以进行寻呼。
- (void)loadMoreMessages { if (!lastMessageKey) { // Loading messages first time [[[msgsReference queryOrderedByKey] queryLimitedToLast:K_MESSAGES_PER_PAGE] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) { if (snapshot.exists) { for (FIRDataSnapshot *child in snapshot.children) { NSMutableDictionary *dict = [child.value mutableCopy]; [dict setObject:child.key forKey:@"id"]; [messages addObject:dict]; } lastMessageKey = [[snapshot.children.allObjects firstObject] key]; NSLog(@"%@", messages); } }]; } else { // Paging started [[[[msgsReference queryOrderedByKey] queryLimitedToLast:K_MESSAGES_PER_PAGE + 1] queryEndingAtValue:lastMessageKey] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) { if (snapshot.exists) { NSInteger count = 0; NSMutableArray *newPage = [NSMutableArray new]; for (FIRDataSnapshot *child in snapshot.children) { // Ignore last object because this is duplicate of last page if (count == snapshot.childrenCount - 1) { break; } count += 1; NSMutableDictionary *dict = [child.value mutableCopy]; [dict setObject:child.key forKey:@"id"]; [newPage addObject:dict]; } lastMessageKey = [[snapshot.children.allObjects firstObject] key]; // Insert new messages at top of old array NSIndexSet *indexes = [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [newPage count])]; [messages insertObjects:newPage atIndexes:indexes]; NSLog(@"%@", messages); } }]; } }
这里是您需要的对象的描述:
#define K_MESSAGES_PER_PAGE 50 // A macro defining the numbers in one request msgsReference // Firebase database messages node reference I'm also attaching the screenshot of my db structure for make you more clear lastMessageKey // Is a NSString object which store the first key of last page messages // Is a NSMutableArray storing the result
祝你好运!! (y)的
Swift 3.x
func fetchEarlierMessages(chatGroupId: String, messageKey: String, completion: @escaping ([Message]?) -> ()) { previousMessageRef = root.child("messages").child(chatGroupId) messageValueHandle = previousMessageRef.queryOrderedByKey().queryLimited(toLast: 10).queryEnding(atValue: messageKey).observe(.value, with: { snapshot in var messages: [Message] = [] for child in snapshot.children.allObjects as! [FIRDataSnapshot] { guard var item = child.value as? [String: AnyObject] else { return } item["message_id"] = child.key as AnyObject if let message = self.parseMessage(snapshot: child) { messages.append(message) } } messages.removeLast() completion(messages) }) }
这里的’parseMessage’函数是我的自定义函数,用于将快照转换为消息模型,您可以使用自己的。 消息密钥是您在初始firebase调用中加载的最早消息的密钥。
斯威夫特2017
我想提出一个优雅的解决方案,就像我为火焰基地的这个任务所做的那样。 此方法在初始化和加载更多数据时都调用:
var items: [ItemEntity] = [] var theEndOfResults = false var lastLoadedItem: ItemEntity? { return items.last } func loadItems() { let isLoadingMore = lastLoadedItem != nil Decorator.showStatusBarLoader() self.databaseReference .child("items") .queryOrdered(byChild: "date") .queryEnding(atValue: isLoadingMore ? lastLoadedItem!.date.stringValue : Date.distantFuture.stringValue) .queryLimited(toLast: 5) .observeSingleEvent(of: .value) { snapshot in var items = self.array(from: snapshot) .map { ItemEntity(parentKey: $0.parentKey, dictionary: $0.dict) } self.theEndOfResults = (self.lastLoadedItem == items.last) // prevent loading when it's no more items if isLoadingMore { items.removeFirst() } // removing as the firebase sending a repeated one self.items.append(contentsOf: items) self.reloadData() } }
用于在控制器中重新加载数据的function。
override func reloadData() { tableV.reloadData() refreshControl.endRefreshing() tableV.loadControl?.endLoading() Decorator.hideStatusBarLoader() }
当用户到达tableView的末尾时调用此方法。
@objc public func loadMore() { guard self.theEndOfResults == false else { tableV.loadControl?.endLoading(); return } self..loadItems() }
从快照制作数组
func array(from snapshot: DataSnapshot) -> [ParseResult] { var items = [ParseResult]() if let snapshots = snapshot.children.allObjects as? [DataSnapshot] { for snap in snapshots { if let postDictionary = snap.value as? Dictionary { items.append((snap.key, postDictionary)) } } } print("🥑 DATA COME:\r\(snapshot)") //or u can use: dump(items, indent: 2, maxDepth: 5, maxItems: 15) return items.reversed() }
感谢这段video ,用“酷”的火力基础参考API澄清了一些时刻。
祝发展好运 ,如果发现不清楚的话,可以提出任何问题。