0

here is relevant for my question part of my code and it works almost fine, except one thing. The data is always sorted randomly. About code: i should receive data (name of CoffeeShop and .jpg) from firebase and display the foto in tableView

var coffeeShopLists: [CoffeeShopList] = []

struct CoffeeShopList {
    let name: String
    let shopImage: UIImage
}

func loadShops () {
        coffeeShopLists = []
        db.collection("coffeeShop").getDocuments { (querySnapshot, error) in
            if let e = error {
                print("Error\(e)")
            } else {
                if let snapshotDocuments = querySnapshot?.documents {
                    for doc in snapshotDocuments {
                        let data = doc.data()
                        print(doc.data())
                        if let shop = data["name"] as? String {
                            print(shop)
                             self.getFoto(named: shop)
//                            self.coffeeShopLists.append(shopList)  //retrieving Data from firebase
                            DispatchQueue.main.async {
                                self.tableView.reloadData()
                            }
                        }
                    }
                }
            }
        }      
    }

func getFoto (named: String) {
        let storage = Storage.storage().reference().child("CoffeeShops/\(named).jpg")
        storage.getData(maxSize: 1 * 1024 * 1024) {data, error in
        if let error = error {
           return print(error)
        } else {
            if let image = UIImage(data: data!) {
                let newList = CoffeeShopList(name: named, shopImage: image)
                self.coffeeShopLists.append(newList)
            DispatchQueue.main.async {
                self.tableView.reloadData()
            }
        }

    }
          
   }        
 }

override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.register(UINib(nibName: "CoffeeShopCell", bundle: nil), forCellReuseIdentifier: "ReusableCell")
        loadShops()
    }

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "ReusableCell", for: indexPath) as! CoffeeShopCell
        cell.shopImage.image = coffeeShopLists[indexPath.row].shopImage
        return cell
    }

How i said: it works. but it should be sorted how it sorted in firebase collection.But its not. And sorry for my english.(

after editing code like in comments bellow ordering by Position.Here is the result of print statements:

["position": 1, "name": soren]
soren
["position": 2, "name": ramozoti]
ramozoti
["position": 3, "name": coffeesoul]
coffeesoul //until this part the result is always the same(correct) and it should be by this order. But the results bellow is always in random order. That part belong to function getFoto()
coffeesoul
[CoffeeShop.CoffeeShopList(name: "coffeesoul", shopImage: <UIImage:0x600000e17600 anonymous {1080, 1080}>)]
ramozoti
[CoffeeShop.CoffeeShopList(name: "coffeesoul", shopImage: <UIImage:0x600000e17600 anonymous {1080, 1080}>), CoffeeShop.CoffeeShopList(name: "ramozoti", shopImage: <UIImage:0x600000e17840 anonymous {621, 621}>)]
soren
[CoffeeShop.CoffeeShopList(name: "coffeesoul", shopImage: <UIImage:0x600000e17600 anonymous {1080, 1080}>), CoffeeShop.CoffeeShopList(name: "ramozoti", shopImage: <UIImage:0x600000e17840 anonymous {621, 621}>), CoffeeShop.CoffeeShopList(name: "soren", shopImage: <UIImage:0x600000e10000 anonymous {1080, 1080}>)]

the struct feels each time by the random order

So, im on the right way. The last question to finish it:How i can sort this struct by the third value

[CoffeeShop.CoffeeShopList(name: "ramozoti", shopImage: Optional(<UIImage:0x600003b27de0 anonymous {621, 621}>), position: 2), CoffeeShop.CoffeeShopList(name: "soren", shopImage: Optional(<UIImage:0x600003b34480 anonymous {1080, 1080}>), position: 1), CoffeeShop.CoffeeShopList(name: "coffeesoul", shopImage: Optional(<UIImage:0x600003b31b00 anonymous {1080, 1080}>), position: 3)]

This is it, its working now. i made extra function

  func sort () {
      
        sortedShopLists = coffeeShopLists.sorted {$0.position < $1.position}
    }

and passt it into getFoto() function after self.coffeeShopLists.append(newList) maybe it was somewhere more elegant way to solve my problem but i found just this.

  • What about using [order(by:)](https://firebase.google.com/docs/firestore/query-data/order-limit-data#swift)? – Joakim Danielson Jun 18 '20 at 20:30
  • "it should be sorted how it sorted in firebase collection" Why would it be? It doesn't _arrive_ in that order. Because, asynchronous. – matt Jun 18 '20 at 20:32

3 Answers3

0

If you don't specify an order of documents in the query, Firestore doesn't guarantee one. Documents are not fundamentally ordered except by what you specify in the query. So, if ordering is important to you, you'll have to arrange for that yourself.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
0

I am a learner on Swift and was facing the same problem, i figured out the way by using .order

db.collection(Constants.FStore.collectionName).order(by: Constants.FStore.dateField).addSnapshotListener { (querySnapShot, error) in

while persisting, i persisted a date field also and I am ordering by that. You can order by a different field.

your code could be

db.collection("coffeeShop").order(by: <<your field>>).getDocuments { (querySnapshot, error)

As I said, I am learner of Swift but I hope this would help.

peeyush
  • 1
  • 1
  • yes, i made that. But still they are always randomnly orginized.i looked the path with print statements , where its going wrong. in function loadFoto() its grabing data how it should be, but then by calling function getFoto() its grabing names randomly. – Aslan Azdaev Jun 19 '20 at 19:53
0

The Firestore console orders the documents by their key. If you want the same in your code, you can

db.collection("coffeeShop")order(by: FieldPath.documentID()).getDocuments(...

Also see: Order by document id firestore?


Your update and comments point towards this being about the loading of the photo's related to those documents.

The loading of the photos starts in the correct order. But since each photo takes a different amount of time to load, it may complete in another order.

If you want the photos to appear in the order that you had the documents, you should make sure you work from a list that maintains the document order.

For example, you could add each document to coffeeShopLists before you start loading its photo, and then update the item in coffeeShopLists with the photo.

So in your loadFotos you'd do sometihng like this:

for doc in snapshotDocuments {
    let data = doc.data()
    if let shop = data["name"] as? String {
        self.coffeeShopLists.append(shopList)
        self.getFoto(named: shop, self.coffeeShopLists.length - 1)
        DispatchQueue.main.async {
            self.tableView.reloadData()
        }
    }
}

The change here is that we're passing the index of the document into the getFoto function, so that it knows which element in the array to update.

Then in getFoto you'd fine the array item and update that in stead of adding a new item.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • yes, i made that. But still they are always randomnly orginized.i looked the path with print statements , where its going wrong. in function loadFoto() its grabing data how it should be, but then by calling function getFoto() its grabing names randomly. – Aslan Azdaev Jun 19 '20 at 19:42
  • Ah, that is quite different. The loading of the photos **starts** in the correct order. But since each photo takes a different amount of time to load, it may **complete** in another order. – Frank van Puffelen Jun 19 '20 at 22:22
  • Some part of answer was useful.Thnx. But solution didnt work for me. But i made some changes, that im grabbing from firebase in func loadsShops name and position(i've made there extra key "Position". And now it feels my struct like this:(name: "ramozoti", shopImage: {621, 621}>), position: 2). And the question is: How i can order it by "position"? i tried a different ways, but didnt find the correct solution. – Aslan Azdaev Jun 23 '20 at 15:43