Learn Courses My Dashboard

Help with firebase document retrieve data

Hello .
I hope you all doing well .
I have small problem with retrieve data array from firebase … please help me with that

my code from cartView to setData to firebase in documents with user id

        sharedData.cartPopular.forEach { (popular) in

            orderMenuDetails.append([

                "title" : popular.title,
                "price" : popular.price,
                "quantity" : popular.quantity

            ])
        }
       // Auth.auth().currentUser!.uid
        db.collection("ORDERS").document(Auth.auth().currentUser!.uid).setData([
                        
            "order" : orderMenuDetails,
            "total" : sharedData.TotalPrice(),
            "name": appStorage.fullName,
            "adress": appStorage.homeAdress,
            "phone": appStorage.phoneNumber,
            "city": appStorage.city,
            "order_time": date,
            "location": homeDataModel.userAddress

        ]) { (err) in
            if err != nil {
                return
            }
            print("All good")
        }
    }

and that is how its look in firebase

and the code to retrieve the array data to my app

struct order :Codable {
   // var id : String
    var price : Int
    var quantity : Int
    var title : String

}

struct orderData :Identifiable, Codable {

    var id : String
    var adress : String
    var location : String
    var city : String
    var name : String
   // var order_time : Date
    var phone : String
    var total : String
    var orderDetails : [order]?
}

class OrderDataModel: ObservableObject {
   @Published var orderDatafb : [orderData] = []
    @Published var orderDetails : [order] = []
    
    init() {

        fetchData()
    }

    func fetchData() {

        let db = Firestore.firestore()

        db.collection("ORDERS").document(Auth.auth().currentUser!.uid).getDocument(completion: { documentSnapshot, error in
            if let err = error {
                 print(err.localizedDescription)
                 return
             }

            if let doc = documentSnapshot {
                let id = doc.documentID
                let adress = doc.get("adress") as! String
                let location = doc.get("location") as! String
                let city = doc.get("city") as! String
                let name = doc.get("name") as! String
                let phone = doc.get("phone") as! String
                let total = doc.get("total") as! String
                let orderDetails = doc.get("order") as! [Any]
                
                self.orderDatafb.append(orderData(id: id, adress: adress, location: location, city: city, name: name, phone: phone, total: total))

                
                
                for item in orderDetails {
                    print(item)
                    
                }

            }
        })

and the printing in debug

2022-01-15 17:59:35.464383+0200 DeliveryRestaurant[1548:20383] 8.9.1 - [Firebase/Firestore][I-FST000001] WatchStream (7ff2e0b1a568) unwatch: <ListenRequest 0x7000047572a8>: {
  database: "projects/deliveryrestaurant-d81a4/databases/(default)"
  remove_target: 14
}
{
    price = 33;
    quantity = 1;
    title = "Beef grilled";
}
{
    price = 7;
    quantity = 2;
    title = "Mash burger";
}

no matter how much I try to append the data to empty array or try to store the retrieve data so I can show it up in content view I always get error some where or back to nil !!
my question is : how can I store the data in array so I can show it up in view …

please I am stuck with this for a 3 days :frowning: help me with that …

thank you …

Hey, I’m going to take a shot at this! Seems like a weird problem indeed. What’s your ContentView look like now?

(I’m asking this in the off-chance by the time you answer, me trying to set something up would be working as well).

@Mohammed2021 I may have solved your problem :crossed_fingers:

I couldn’t find anywhere where you were updating your precious orderDetails property, nor adding orderDetails to the orderDetails property in the orderData object that you append to orderDatafb.

You add all of the other properties to the orderData object. In this long line:

self.orderDatafb.append(orderData(id: id, adress: adress, location: location, city: city, name: name, phone: phone, total: total))

I recommend breaking this line up, so it becomes clearer:

self.orderDatafb.append(
    orderData(
        id: id,
        adress: adress,
        location: location,
        city: city,
        name: name,
        phone: phone,
        total: total
    )
)

Notice anything missing? After the total property, you forgot to add the orderDetails property. So it should look like this instead:

self.orderDatafb.append(
    orderData(
        id: id,
        adress: adress,
        location: location,
        city: city,
        name: name,
        phone: phone,
        total: total,
        orderDetails: orderDetails
    )
)

Also, you never update the orderDetails property of the OrderDataModel. Honestly, this property is redundant, because your orderDatafb property already contains this same data as a list in one of its properties. Still, it’s easier to access the orderDetails by having it as a property as you do.

So to do this, you add the following line above before your for loop:

self.orderDetails = orderDetails

Also, when getting your orderDetails from Firebase, I recommend decoding it as an order type, versus the Any type of list. So you change this line:

let orderDetails = doc.get("order") as! [Any]

To:

let orderDetails = doc.get("order") as! [order]

Let me know, if this works! Thanks for posting example data, as well as all of this code, so far :slight_smile: Looks like this was a simple mistake, and it helps to have someone else review your code.

Cheers,
Andrew

how many times should I say thank you ? 1000 times I think not enough , I never thought should replace [Any] with [order] . I added it orderDetails:orderDetails before it was give me error with can’t convert type order with [order] , and I replaced ! with ? cuz it was crashing the app, error back nil . any way so far so good but …

I got empty view when loop in side order array …
I think the order array is empty ?

struct OrderHistoryView: View {
    @StateObject var getOrderFb = OrderDataModel()
    
    var body: some View {
        
        VStack {
            
            
            ForEach(getOrderFb.orderView) { i in
                
                Text(i.title)
            }     
        }
        
    }
}

struct OrderHistoryView_Previews: PreviewProvider {
    static var previews: some View {
        OrderHistoryView()
    }
}

struct order :Identifiable, Codable,Hashable {
    var id : String
    var price : Int
    var quantity : Int
    var title : String

}

struct orderData :Identifiable, Codable {

    var id : String
    var adress : String
    var location : String
    var city : String
    var name : String
   // var order_time : Date
    var phone : String
    var total : String
    var orderDetails : [order]?
    
}

class OrderDataModel: ObservableObject {
   @Published var orderDatafb : [orderData] = []
    @Published var orderView : [order] = []
    
    init() {

        fetchData()
        
    }

    func fetchData() {

        let db = Firestore.firestore()

        db.collection("ORDERS").document(Auth.auth().currentUser!.uid).getDocument(completion: { documentSnapshot, error in
            if let err = error {
                 print(err.localizedDescription)
                 return
             }

            if let doc = documentSnapshot {
                let id = doc.documentID
                let adress = doc.get("adress") as! String
                let location = doc.get("location") as! String
                let city = doc.get("city") as! String
                let name = doc.get("name") as! String
                let phone = doc.get("phone") as! String
                let total = doc.get("total") as! String
                let orderDetails = doc.get("order") as? [order]
                
                self.orderDatafb.append(orderData(id: id, adress: adress, location: location, city: city, name: name, phone: phone, total: total,orderDetails: orderDetails))
                
                
            }
        })
        

Hey Muthana, you’re most welcome :slight_smile: so glad that fixed part of the problem!

As far as this, I don’t see anywhere, where you update the orderView property. Therefore, it’s likely empty.

You would add this line, below the append to the orderDatfb property to add data to the orderView list of orders:

self.orderDatafb.append(orderData(id: id, adress: adress, location: location, city: city, name: name, phone: phone, total: total,orderDetails: orderDetails))

self.orderView.append(orderDetails)

This should fix your current View code.

Or in your View code, you could loop through the orderDetails property of the orderDatafb of your OrderDataModel.

So change this:

VStack {
    ForEach(getOrderFb.orderView) { i in
        Text(i.title)
    }
}

To this:

VStack {
    ForEach(getOrderFb.orderDatafb.orderDetails) { i in
        Text(i.title)
    }
}

Better yet, you might want to check if there are any orders, so maybe this code instead:

VStack {
    // Ensure there is at least one order
    if getOrderFb.orderDatafb.orderDetails.count > 0 {
        ForEach(getOrderFb.orderDatafb.orderDetails) { i in
            Text(i.title)
        }
    }
    else {
        Text("Please add an item to your order.")
    }
}

sorry for take so long … but I am trying to find what’s wrong … I did update the array before and got this error

self.orderView.append(orderDetails) // error msg : No exact matches in call to instance method 'append'

and I am already Decoded

finally I got it …

thank you so much for helping me , I hope this solution can help every one stuck with that .
thank you again .

1 Like

Excellent work!! :partying_face:

You’re most welcome

I’m happy you got everything functioning. Way to stick it out :slight_smile:

I’d be curious to see your finished app as well!

Cheers,
Andrew

1 Like