首页 > 解决方案 > Cannot convert value of type '()' to expected argument type '(Data?, URLResponse?, Error?) -> Void'

问题描述

I can't solve this error I hope can I find the solution here the error is in the line 22 and it's "Cannot convert value of type () to expected argument type (Data?, URLResponse?, Error?) -> Void"

enter image description here

struct WeatherManager {
    let weatherURL = ""
    func fetchWeather(cityName : String){
        let urlString = "\(weatherURL)&q=\(cityName)"
        performRequest(urlString: urlString)
    }
    func performRequest(urlString : String){
        //1- Create a URL
        if let url = URL(string: urlString){
            //2- Create a URLSession
            let session = URLSession(configuration: .default)
            //3- Give the session a task
            let task = session.dataTask(with: url, completionHandler:handel(data: <#T##Data?#>, urlSession: <#T##URLSession?#>, error: <#T##Error?#>))
            //4- Start the Task
            task.resume()
        }
    }
    func handel(data:Data? , urlSession : URLSession? , error : Error?){
        if error != nil {
            print(error!)
            return
        }
        if let safeData = data{
            let dataString = String(data: safeData, encoding: .utf8)
            print(dataString!)
        }
    }
}

here is the error :

let task = session.dataTask(with: url, completionHandler:handel(data: <#T##Data?#>, urlSession: <#T##URLSession?#>, error: <#T##Error?#>))

标签: swift

解决方案


A few observations:

  1. The signature of “handle” is incorrect. The second parameter is a URLResponse, not a URLSession:

    func handle(data: Data?, response: URLResponse?, error: Error?) {
        if let error = error {
            print(error)
            return
        }
        if let data = data, let string = String(data: data, encoding: .utf8) {
            print(string)
        }
    }
    

    As Leo pointed out, you should avoid force-unwrapping with the ! operator, too (especially when converting the Data to a UTF8 String).

  2. You should not supply parameters when you pass handle to dataTask:

    func performRequest(urlString: String) {
        //1- Create a URL
        guard let url = URL(string: urlString) else { return }
        //2- Use existing URLSession
        let session = URLSession.shared // (configuration: .default)
        //3- Give the session a task
        let task = session.dataTask(with: url, completionHandler: handle)
        //4- Start the Task
        task.resume()
    }
    

Unrelated, please note that I have not created a URLSession in performRequest. Sessions will leak memory if you create them but do not invalidate them. In this case, it is easier to use the existing shared session, rather than creating a new one.

If you really needed to create one (which you obviously do not in this case ... use shared instead), you would explicitly tell it to invalidate itself when the request was done.

func performRequest(urlString: String) {
    //1- Create a URL
    guard let url = URL(string: urlString) else { return }
    //2- Create URLSession (but only if absolutely necessary)
    let session = URLSession(configuration: .default)
    //3- Give the session a task
    let task = session.dataTask(with: url, completionHandler: handle)
    //4- Start the Task
    task.resume()
    //5- If you really must create a session, invalidate it when the request(s) are finished
    session.finishTasksAndInvalidate()
}

But this is an anti-pattern because it is so inefficient. You should reuse a single session, like shown in the previous code snippet, if at all possible.


推荐阅读