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 @Published
var 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 getDevices
every time the value changes.