简体   繁体   中英

Appending array in swift values mixed up

I am trying to get data from a Firestore Database which looks like:

texts - 1 - message (String)
            author (String)
      - 2 - message (String)
            author (String)
      ...

For testing purposes the data I am setting the message String to be is "test" + the number that they are contained in (eg 1 would be test1)

The code I am using to display these in a stack view as labels is:

if startNumOfMessages > 0 {
    let g = DispatchGroup()
    for message in stride(from: startNumOfMessages, through: 1, by: -1) {
        g.enter()
        print(message)
        db.collection("chats").document(self.userDefaults.string(forKey: "currentGroup")!).collection("texts").document("\(message)").getDocument { (doc, err) in
            if err != nil{
                print("Error getting message \(message)")
            }
            else{
                if doc!.exists{
                    let messData = doc!.data()
                    messageArray.append(messData!["message"] as! String)
                    authorArray.append(messData!["author"] as! String)
                }
                else{
                    print("Document Doesnt exist")
                }
            }
            g.leave()
        }
    }
    //Display them
    g.notify(queue: .main){
        print(messageArray)
        for num in stride(from: messageArray.count - 1, through: 0, by: -1){
            let authorLabel = UILabel()
            authorLabel.text = authorArray[num]
            authorLabel.font = UIFont(name:"SF Pro", size: 10.0)
            authorLabel.textColor = UIColor.lightGray
            self.stackView.addArrangedSubview(authorLabel)
            let label = UILabel()
            label.text = messageArray[num]
            self.stackView.addArrangedSubview(label)
        }
    }
}

However when I print(messageArray) the array comes out as

["test1", "test3", "test2", "test4", "test5"]

So my question is why does this happen? I have tried messing about with the loops but they seem fine and I have checked the data that it is getting and there is nothing incorrect there.

My guess is that there is no guarantee that the getDocument completion closures will be called in the same order as the order you call getDocument. Eg one may come from local cache, other from network so may get reordered.

EDIT 2:

Sorry, you don't need order(by: .

I checked the code in your question again, and everything i have written in my answer seems to be irrelevant. Since you are retrieving from texts collection using document("\(message)") , where message is ctually the count, the only explainatin is your data must be incorrect. ie you must have set test3 in object numbered 2 , and vice versa.

An easy way to verify this is to add following print statement before / after the code to append text to your messageArray :

if let messageString = messData?["message"] as? String {
    print("text #: \(message) - message: \(messageString)")
}

Old answer (kept here just for reference)

As mentioned in my comment in Order and limit data with Cloud Firestore it is clearly mentioned:

By default, a query retrieves all documents that satisfy the query in ascending order by document ID. You can specify the sort order for your data using orderBy()

Meaning, the sort torder you expect for your data (by messsage text, or order in which you entered the data), is not default / guaranteed.

Just use .order(by: "message") to get the data in you required order.

EDIT:

You needto apply sort on a collection. So, instead of:

.collection("texts")

you need to do use:

.collection("texts").order(by: "message")

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