1

I store a value called month hours in my application that keeps track of the hours a person has used the apps and displays it in a line of text. The text if part of a stack in Swift UI, but I can't figure out how to make the text update once the information has been queried from I've tried quite a few ways of making this work from structs to classes to using @State.

This is just the latest thing I tried that didn't work if anyone can help that would be greatly appreciated.

let db = Firestore.firestore()


class Month {
    var monthHours = "0"

    func getMonthHours() {
        db.addSnapshotListener(.  //Im removing the actual query part to keep that private but the print statement below confirms the query is not the issue. 
            { (docSnapShot, err) in
                if let e = err {
                    print("There was an error retrieving the monthly hours:\n\(e.localizedDescription)")
                } else {
                    let data = docSnapShot?.data()
                    if let h = data?[K.FStore.monthHoursField] as? Double {
                        self.monthHours = String(h.rounded())
                        print("These are the hours:\n\(self.monthHours)")
                    }
                }
        })
    }
    func getMonth() -> String {
            let date = Date()
            let formatter = DateFormatter()
            formatter.dateFormat = "MMMM yyyy"
            let result = formatter.string(from: date)
            return result
    }
    init() {
        getMonthHours()
    }
}

struct ChartView : View {
    @State private var month = Month()
    //Struct variables
    var body  : some View {
        ZStack {
            Color(UIColor(named: K.BrandColors.grey)!).edgesIgnoringSafeArea(.all)
            VStack {
                Text("HOURS THIS MONTH \(month.monthHours)")
                    .font(.system(size: 18))
                    .fontWeight(.heavy)
            }
        } 
} 

1 Answer 1

2

This outlines one possible approach. The crux is to deal with the asynchronous function "getMonthHours". You need to wait till it is finished its fetching before you can use the results.

class Month {
    var monthHours = "0"

    // async fetch the month hours from Firestore, ... error handling todo
    static func getMonthHours(handler: @escaping (String) -> Void) {
        db.addSnapshotListener{ (docSnapShot, err) in
            if let e = err {
                print("There was an error retrieving the monthly hours:\n\(e.localizedDescription)")
                return handler("") // should return some error here .... todo
            } else {
                if let data = docSnapShot?.data(),
                    let h = data?[K.FStore.monthHoursField] as? Double {
                    // return the result
                    return handler(String(h.rounded()))
                } else {
                    return handler("") // should return some error here .... todo
                }
            }
        }
    }

    func getMonth() -> String {
        let date = Date()
        let formatter = DateFormatter()
        formatter.dateFormat = "MMMM yyyy"
        let result = formatter.string(from: date)
        return result
    }

    init() { }
}

struct ChartView : View {
@State private var monthHours = ""
var body  : some View {
    ZStack {
        Color(UIColor(named: K.BrandColors.grey)!).edgesIgnoringSafeArea(.all)
        VStack {
            Text("HOURS THIS MONTH \(monthHours)")
                .font(.system(size: 18))
                .fontWeight(.heavy)
        }
    }.onAppear(perform: loadData)
    }
}

func loadData() {
    // when the fetching is done it will update the view
    Month.getMonthHours() { hours in
        self.monthHours = hours
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much that helped out a lot you have no idea how long I was trying to debug that haha! Much appreciated!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.