I'm trying to return a value from an API function with dataTask. When editing the code, I get the error:
Type of expression is ambiguous without more context.
I added the code below. Does anyone know how to fix this? I'm new to Swift.
func getNonce() {
let headers = [
"accept": "application/json",
"content-type": "application/json"
]
let parameters = [
"id": 1,
"jsonrpc": "2.0",
"params": [addressETH, "pending"],
"method": "eth_getTransactionCount"
] as [String : Any]
let postData = try? JSONSerialization.data(withJSONObject: parameters, options: [])
let request = NSMutableURLRequest(url: NSURL(string: "https://eth-goerli.g.alchemy.com/v2/myapikeygoeshere")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData! as Data
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> String in
if (error != nil) {
print(error as Any)
} else {
let dataString = String(data: data!, encoding: .utf8)!
let start = dataString.index(dataString.startIndex, offsetBy: 36)
let end = dataString.index(dataString.endIndex, offsetBy: -2)
let range = start..<end
let user_Nonce = String(dataString[range])
return user_Nonce?
}
})
dataTask.resume()
}
The error is on this line:
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> String in
I tried to return the value but the error popped up.
CodePudding user response:
You should read up on how completion handlers or async await work in swift. Here are some examples on how you could structure this function to work - and you'll have to account for the completion handler or async await at the call site. There are also a fair number of force unwraps (!
) in here, which you should avoid, same with try?
. Catch those conditions and report the errors to the caller.
// Example using closures
func getNonce(completion: @escaping (Result<String, Error>) -> Void) {
let headers = [
"accept": "application/json",
"content-type": "application/json"
]
let parameters = [
"id": 1,
"jsonrpc": "2.0",
"params": ["addressETH", "pending"],
"method": "eth_getTransactionCount"
] as [String : Any]
let postData = try? JSONSerialization.data(withJSONObject: parameters, options: [])
var request = URLRequest(url: NSURL(string: "https://eth-goerli.g.alchemy.com/v2/myapikeygoeshere")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData!
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
completion(.failure(error))
} else {
let dataString = String(data: data!, encoding: .utf8)!
let start = dataString.index(dataString.startIndex, offsetBy: 36)
let end = dataString.index(dataString.endIndex, offsetBy: -2)
let range = start..<end
let user_Nonce = String(dataString[range])
completion(.success(user_Nonce))
}
}
task.resume()
}
// Example using async await
func getNonce() async throws -> String {
let headers = [
"accept": "application/json",
"content-type": "application/json"
]
let parameters = [
"id": 1,
"jsonrpc": "2.0",
"params": ["addressETH", "pending"],
"method": "eth_getTransactionCount"
] as [String : Any]
let postData = try? JSONSerialization.data(withJSONObject: parameters, options: [])
var request = URLRequest(url: NSURL(string: "https://eth-goerli.g.alchemy.com/v2/myapikeygoeshere")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData!
let (data, _) = try await URLSession.shared.data(for: request)
let dataString = String(data: data, encoding: .utf8)!
let start = dataString.index(dataString.startIndex, offsetBy: 36)
let end = dataString.index(dataString.endIndex, offsetBy: -2)
let range = start..<end
let user_Nonce = String(dataString[range])
return user_Nonce
}
// Assuming called from viewDidLoad in a view controller
override func viewDidLoad() {
super.viewDidLoad()
// How to call using closure example
getNonce { result in
switch result {
case .success(let nonce):
print("got nonce: \(nonce)")
case .failure(let error):
// handle error
break
}
}
// How to call using async await example
Task {
do {
let nonce = try await getNonce()
print("got nonce: \(nonce)")
} catch {
// handle error
}
}
}