Home > Net >  How can I use the return from my function as an argument for another function in onAppear
How can I use the return from my function as an argument for another function in onAppear

Time:03-31

I am trying to use the result of the following function:

class GetRefresh: ObservableObject {
   let user = Auth.auth()
   var ref = Database.database().reference()
   @Published var refreshToken = ""
   func getRefresh() {
       ref.child("\(user.currentUser!.uid)").child("refreshUrl").getData { error, snapshot in
        guard error == nil else {
            print(error!.localizedDescription)
            return
        }
        let refreshUrl = snapshot.value as? String ?? "Unknown"
        let url = URL(string: refreshUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!)
        var request = URLRequest(url: url!)
        request.httpMethod = "POST"
        URLSession.shared.dataTask(with:request) { (data, response, error) in
          if error != nil {
            print(error)
          } else {
            do {
              let parsedData = try JSONSerialization.jsonObject(with: data!) as! [String:Any]
              let token = parsedData["access_token"] as? String
              self.refreshToken = token!
            } catch let error as NSError {
              print(error)
            }
          }
        }.resume()
    }
  }
}

To pass as an argument to a Async service that is called in the onAppear of my view:

struct DevicesTab: View {
   @StateObject var callDevices = CallDevices()
   @StateObject var getRfrsh = GetRefresh()
   var ref: DatabaseReference!
   var body: some View {
       VStack(spacing: 0) {
           greeting.edgesIgnoringSafeArea(.top)
           messages
           Spacer()
       }
      .onAppear {
          getRfrsh.getRefresh()
          callDevices.getDevices(refreshToken: getRfrsh.refreshToken) //this fails
          }
      }
   }

The callDevices.getDevices is using the argument as a Header for its URLRequest.

If i hardcode the token in onAppear like:

.onAppear {
   getRfrsh.getRefresh()
   callDevices.getDevices(refreshToken: "HardcodedToken") //this works
  }

It works fine, albeit with a bit of a delay before the data is loaded but it works... I am sure the function is returning correctly as I was able to print it in GetRefresh.

CodePudding user response:

Well the reason for your code failing is you are not waiting for the network call to be completted before you call the next method.

Solution:

You could rework the code to be async. Or you could observe the changes of your @Publishedvar and call getDevices.

.onChange(of: getRfrsh.refreshToken) { newValue in
            callDevices.getDevices(refreshToken: newValue)
        }
.onAppear {
// to avoid repeatitive refreshing
      if getRfrsh.refreshToken == ""{
         getRfrsh.getRefresh()}
      }

But be aware. This will call getDevicesevery time the value changes.

  • Related