I'm trying to pass a Double value from a function called from another view and the function returns a value before the AlamoFire request completes
struct GetPrice {
static func getThePrice(book: String) async -> Double? {
var theNetPrice: Double = 0.0
var iListPrice = ""
let url = "https://example.com"
let headers: HTTPHeaders = [
"accept": "application/xml",
"Authorization": "Basic \xxx",
"Content-Type": "application/x-www-form-urlencoded"
]
let body: [String: Any] = ["xxxxx"]
AF.request(url, method: .post, parameters: body, encoding: URLEncoding.default, headers: headers)
.responseData { response in
var statusCode = response.response?.statusCode
//print("response.result ", response.result)
switch response.result {
case .success:
let data = response.data
let s = String(data: data!, encoding: .utf8)
let xml = XMLHash.parse(String(s!))
iListPrice = xml["xxx"].element!.text
theNetPrice = Double(iListPrice)
print(theNetPrice) // this shows correct value
//return theNetPrice -- this would give error 'Cannot convert value of type 'Double' to closure result type 'Void''
case .failure(let error):
statusCode = error._code
print("status code is: \(String(describing: statusCode))")
print(error)
}
}
return theNetPrice //returns 0.0
}
}
'''
Try this approach using a continuation
as shown in the example code.
struct GetPrice {
static func getThePrice(book: String) async -> Double? {
//..
return await withCheckedContinuation { continuation in
AF.request(url, method: .post, parameters: body, encoding: URLEncoding.default, headers: headers)
.responseData { response in
var statusCode = response.response?.statusCode
//print("response.result ", response.result)
switch response.result {
case .success:
let data = response.data
let s = String(data: data!, encoding: .utf8)
let xml = XMLHash.parse(String(s!))
iListPrice = xml["xxx"].element!.text
theNetPrice = Double(iListPrice)
print(theNetPrice) // this shows correct value
continuation.resume(returning: theNetPrice)
case .failure(let error):
statusCode = error._code
print("status code is: \(String(describing: statusCode))")
print(error)
continuation.resume(returning: theNetPrice)
}
}
}
}
}
Use it with something like
Task {
let price = await GetPrice.getThePrice(book: "MyBook")
if let price = price {
print("The price is: \(price)")
}
}
Or you could try using a completion handler, such as
static func getThePrice(book: String, completion: @escaping (Double?) -> Void) {
//..
AF.request(url, method: .post, parameters: body, encoding: URLEncoding.default, headers: headers)
.responseData { response in
var statusCode = response.response?.statusCode
//print("response.result ", response.result)
switch response.result {
case .success:
let data = response.data
let s = String(data: data!, encoding: .utf8)
let xml = XMLHash.parse(String(s!))
iListPrice = xml["xxx"].element!.text
theNetPrice = Double(iListPrice)
print(theNetPrice) // this shows correct value
completion(theNetPrice)
case .failure(let error):
statusCode = error._code
print("status code is: \(String(describing: statusCode))")
print(error)
completion(theNetPrice)
}
}
}
Use it like this:
GetPrice.getThePrice(book: "MyBook") { price in
if let price = price {
print("The price is: \(price)")
}
}