Как выполнить запрос разбиения на страницы в SDK Firebase iOS?

Firebase Model

Это моя модель.

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)? С началом и смещением. Как я могу запросить это?

Ответ 1

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:

Ответ 2

Слишком много времени я выяснил, и вот решение. Это Objective-C код, который вы можете преобразовать в быстрый. Функция вызова ниже для целей пейджинга.

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

Удачи! (У)

введите описание изображения здесь

Ответ 3

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.

Ответ 4

Swift 2017

Я хотел бы представить элегантное решение, которое я мог бы сделать для этой задачи разбиения на страницы с помощью firebase. Этот метод называется как при инициализации, так и при загрузке большего количества данных:

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 no more items
                if isLoadingMore { items.removeFirst() } // removing as the firebase sending a repeated one
                self.items.append(contentsOf: items)

                self.reloadData()
        }
    }

Функция перезагрузки данных в контроллере.

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<String, AnyObject> {
                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()
}

Спасибо этому видео, чтобы прояснить некоторые моменты с помощью "крутой" справки о базовой бомбе. api. Удачи в разработке и задайте любые вопросы, если найдете что-то непонятное.