Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
798 views
in Technique[技术] by (71.8m points)

ios - Contextual closure type '(Data?, URLResponse?, Error?) -> Void' expects 3 arguments, but 1 was used in closure body

I am following this tutorial but getting this error:

Contextual closure type '(Data?, URLResponse?, Error?) -> Void' expects 3 arguments, but 1 was used in closure body

at line: urlSession.dataTask(with: url) { (result) in

private func fetchResources<T: Decodable>(url: URL, completion: @escaping (Result<T, APIServiceError>) -> Void) {
    guard var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: true) else {
        completion(.failure(.invalidEndpoint))
        return
    }
    let queryItems = [URLQueryItem(name: "api_key", value: apiKey)]
    urlComponents.queryItems = queryItems
    guard let url = urlComponents.url else {
        completion(.failure(.invalidEndpoint))
        return
    }

    urlSession.dataTask(with: url) { (result)  in
        switch result {
            case .success(let (response, data)):
                guard let statusCode = (response as? HTTPURLResponse)?.statusCode, 200..<299 ~= statusCode else {
                    completion(.failure(.invalidResponse))
                    return
                }
                do {
                    let values = try self.jsonDecoder.decode(T.self, from: data)
                    completion(.success(values))
                } catch {
                    completion(.failure(.decodeError))
                }
            case .failure(let error):
                completion(.failure(.apiError))
            }
     }.resume()
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

This closure of dataTask is expecting three parameters, a Data?, a URLResponse?, and an Error?. Your code is written as if this closure had a single parameter, a Result. It looks like you thought it was a Result<(Data, URLResponse), Error>, but it’s not. This Result enum is one that we use in our own code, but it’s not used by URLSession.

Thus, change dataTask to use a closure with the three parameters:

private func fetchResources<T: Decodable>(url: URL, completion: @escaping (Result<T, APIServiceError>) -> Void) {
    guard var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: true) else {
        completion(.failure(.invalidEndpoint))
        return
    }
    urlComponents.queryItems = [URLQueryItem(name: "api_key", value: apiKey)]
    guard let url = urlComponents.url else {
        completion(.failure(.invalidEndpoint))
        return
    }

    urlSession.dataTask(with: url) { data, response, error in
        guard error == nil else {
            completion(.failure(.apiError))
            return
        }

        guard 
            let data = data,
            let response = response as? HTTPURLResponse,
            200...299 ~= response.statusCode 
        else {
            completion(.failure(.invalidResponse))
            return
        }

        do {
            let values = try self.jsonDecoder.decode(T.self, from: data)
            completion(.success(values))
        } catch {
            completion(.failure(.decodeError))
        }
    }.resume()
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...