0

I got a class with a function that gets the username for printing it on the view. It works, but I got a delay of nearly a second where the username is not seen.

here the class :

   class ViewModel: ObservableObject {


@Published var username: String = ""





func benutzerdaten_accountview (email: String) -> String {
    let db = Firestore.firestore()
    let docRef = db.collection("Nutzer").document(email)
    docRef.getDocument{ (document, error) in
        
        if let document = document, document.exists{
            self.username = (document.data()!["username"] as? String)!
    }
   }
    return username
  }

}

This is how I print it on the view :

struct AccountView: View{

@ObservedObject var model = ViewModel()
@Binding var tabSelection: Int
var email: String = (Auth.auth().currentUser?.email)!

var body: some View {
    
        VStack{
            
            Text("Hallo, \(model.benutzerdaten_accountview(email: email).description)")
         ...
3
  • I'd be surprised if the correct username is actually returned. By the looks of it, I don't think it would change from the original empty string, until after. So the return is pointless for a value set in an asynchronous closure. Commented Dec 26, 2021 at 0:56
  • And how can I fix it? Commented Dec 26, 2021 at 1:01
  • We don’t use view models in SwiftUI Commented Dec 26, 2021 at 1:37

1 Answer 1

1

In benutzerdaten_accountview(), you can't return username because it isn't already set yet. The username is set in an asynchronous closure.

You are already setting username in the callback closures already, so that's good. What you need to do now is just call the method in onAppear(perform:) so it shows as soon as AccountView loads.

The changing of username will publish an update to update the view again, when it is ready. Fetching data from an API can take time, especially when you have cold-starts.

Firstly, remove the return and the return type in that benutzerdaten_accountview() method. This is no longer needed. Rest of code:

struct AccountView: View {
    @ObservedObject var model = ViewModel()
    @Binding var tabSelection: Int
    var email: String = (Auth.auth().currentUser?.email)!

    var body: some View {
        VStack {
            Text("Hallo, \(model.username)")
        }
        .onAppear {
            model.benutzerdaten_accountview(email: email)
        }
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

It worked. Thank you, but I still got this delay. On the first start of the app the username is blank for a whole second
@kaan5353 That the nature of calling an API on the internet, and also cold-starts as I mentioned. To solve this on the client side, you can save that value locally if you want.

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.