Home > database >  Error: Type of expression is ambiguous without more context
Error: Type of expression is ambiguous without more context

Time:11-18

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
        }
    }
}
  • Related