上下文闭包类型 '(Data?, URLResponse?, Error?) -> Void' 需要 3 个参数,但 1 在闭包主体中使用

Posted

技术标签:

【中文标题】上下文闭包类型 \'(Data?, URLResponse?, Error?) -> Void\' 需要 3 个参数,但 1 在闭包主体中使用【英文标题】:Contextual closure type '(Data?, URLResponse?, Error?) -> Void' expects 3 arguments, but 1 was used in closure body上下文闭包类型 '(Data?, URLResponse?, Error?) -> Void' 需要 3 个参数,但 1 在闭包主体中使用 【发布时间】:2021-01-11 02:19:59 【问题描述】:

我正在学习本教程,但收到此错误:

上下文闭包类型 '(Data?, URLResponse?, Error?) -> Void' 需要 3 个参数,但在闭包主体中使用了 1 个

在线: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()

【问题讨论】:

@Rob 我修复了 URLSession 预期的参数,但现在错误是 switch 语句上的“在范围内找不到'结果'” 这更有意义@Rob 非常感谢! 【参考方案1】:

dataTask 的这个闭包需要三个参数:Data?URLResponse?Error?。你的代码写得好像这个闭包只有一个参数,Result。看起来您认为它是 Result&lt;(Data, URLResponse), Error&gt;,但事实并非如此。这个Result 枚举是我们在自己的代码中使用的枚举,但URLSession 没有使用它。

因此,将dataTask 更改为使用带有三个参数的闭包:

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()

【讨论】:

以上是关于上下文闭包类型 '(Data?, URLResponse?, Error?) -> Void' 需要 3 个参数,但 1 在闭包主体中使用的主要内容,如果未能解决你的问题,请参考以下文章

无法在当前上下文中推断闭包类型

如何修复上下文闭包类型 '((String, JSON), (String, JSON)) -> Bool' 需要 2 个参数,但在闭包体中使用了 1 个?

根据闭包上下文的要求,返回类型“动态”不是“布尔”

上下文闭包类型 Response<AnyObject> -> void 需要 1 个 agrument,但 3 个在闭包主体中

根据闭包上下文的要求,返回类型“Future<Image>”不是“Widget”

闭包参数列表的上下文类型需要 1 个参数,但指定了 4 个