简体   繁体   中英

How can I get a list of children in a Firebase snapshot in order?

I'm working on an app that records when a user stops a scroll motion, appends the offset of the scroll and an elapsed time to a local array, and then uploads the scroll history to Firebase when the user closes the app.

The data in Firebase is stored with an auto ID at the top. Each scroll offset and elapsed time is then stored within its own auto ID child below the parent. In the Firebase web app, the children are in proper order.

I pull the data from Firebase like so:

ghostref.queryOrderedByKey().queryLimited(toLast: UInt(1)).observe(.childAdded, with: { (snapshot) in

       guard let ghostdict = snapshot.value as? [String:[String:String]] else {
            print("failure")
            return
        }

        var downloadedghostarray = [(cameray:Float, timeelapse:Double)]()

        for key in ghostdict.keys {
            downloadedghostarray.append((cameray: Float(ghostdict[key]!["cameray"]!)!, timeelapse: Double(ghostdict[key]!["timeelapse"]!)!))
        }
}

While I get the data I need, it is not in the proper order. Is there any way to pull Firebase children in the expected order? Maybe I can order the snapshot's children by key as well?

EDIT: Here is the data as it appears in the Firebase web app in the desired order:

在此处输入图片说明

And here is the array that renders using the code above:

在此处输入图片说明

By iterating the node fields by key and organizing them by key, you're effectively randomizing the elements in your list. Hash-based dictionaries/maps don't guarantee that order is maintained.

You're going to have to iterate the snapshot using children , which (I believe) ensures that order of the children is maintained. This order should allow you to push them into another array whose order is ensured.

class func downloadAllMessages(forUserID: String, completion: @escaping ([Message]) -> Swift.Void, locationCompletion: @escaping (String) -> Swift.Void) {
    if let userID = Helper.shared.driverLoggedInDetails.detail?.userid {
        let currentUserID = "D\(userID)"

        dbReference.child("users").child(currentUserID).child("conversations_list").child(forUserID).observeSingleEvent(of: .value) { (snapshot) in
            if snapshot.exists() {
                let data = snapshot.value as! [String: Any]
                let location = data["location"]!
                locationCompletion(location as! String)

                dbReference.child("messages").child(location as! String).observe(.childAdded, with: { (snap) in
                    if snap.exists() {

                        let receivedMessages = snap.value as! [String: Any]
                        var messages1 = [Message]()
                        let type = MessageType.text

                        let text = (receivedMessages as NSDictionary).object(forKey: "text") as? String
                        let mmText = (receivedMessages as NSDictionary).object(forKey: "mmText") as? String
                        let messageType = (receivedMessages as NSDictionary).object(forKey: "messageType") as? Int

                        let fromID = (receivedMessages as NSDictionary).object(forKey: "senderId")as? String
                        let timestamp = (receivedMessages as NSDictionary).object(forKey: "timeStamp")as? Int
                        let isRead = (receivedMessages as NSDictionary).object(forKey: "read")as? Bool
                        let isvisible  = UserDefaults.standard.object(forKey: "chatwindow") as? Bool
                        if fromID != currentUserID, isvisible ?? false {
                            dbReference.child("messages").child(location as? String ?? "").child(snap.key).child("read").setValue(true)
                        }

                        if fromID == currentUserID {
                            let message = Message.init(type: type, textEn: text ?? "", textMM: mmText ?? "", owner: .receiver, timestamp: timestamp ?? 0, isRead: isRead ?? false, isSuggested: messageType == -1 ? true : false)
                            messages1.append(message)

                        } else {
                            let message = Message.init(type: type, textEn: text ?? "", textMM: mmText ?? "", owner: .sender, timestamp: timestamp ?? 0, isRead: isRead ?? false, isSuggested: messageType == -1 ? true : false)
                            messages1.append(message)
                        }

                        completion(messages1)
                    }else {
                        // LoadingIndicator.shared.hide()
                        completion([])
                    }
                })
                // LoadingIndicator.shared.hide()
                completion([])
            }
        }
    }
}

U can get by adding a number field in the firebase document from 1..n, so that you can use query based on ascending/ descending. The result will be your expected result

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM