如何修复:"Member 'value' in X produces result of type X, but context expects X" (X == "Either<List, APIError>")

How to fix: "Member 'value' in X produces result of type X, but context expects X" (X == "Either<List, APIError>")

我正在使用 Openweathermap 为基于 Swift 的 iOS 应用设置一个 api 客户端。我遵循了如何设置它的教程,但不得不更换天气提供商,因为他们的服务不再提供免费的 api 密钥。我的客户完成类型有一个错误,但不完全了解发生了什么。本教程使用了模板类型,但我更改了它以尝试解决另一个错误。

我一直在尝试使用模板与非模板化完成格式,但我不明白其目的或它是如何工作的。

class WeatherAPIClient: APIClient {  
    var session: URLSession

    init(session: URLSession = URLSession.shared) {
        self.session = session
    }

    func weather(with endpoint: WeatherEndpoint, completion: @escaping (Either<List, APIError>) -> Void){
        let request = endpoint.request
        self.fetch(with: request) { (either: Either<[List], APIError>) in
            switch either {
            case .value(let weather):
                completion(.value(weather))  // <--- Original error line here
            case .error(let error):
                completion(.error(error))
            }
        }
    }
}
enum Either<List, APIError> { // <-- Error changing this to [List] (comment error 1)
    case value(List)
    case error(APIError)
}

enum APIError: Error {
    case apiError
    case badResponse
    case jsonDecoder
    case unknown(String)
}

protocol APIClient {
    var session : URLSession {get}
    func fetch<List: Codable> (with request: URLRequest, completion: @escaping (Either<[List], APIError>) -> Void)
}


extension APIClient {
    func fetch<List: Codable> (with request: URLRequest, completion: @escaping (Either<[List], APIError>) -> Void){
        let task = session.dataTask(with: request) { (data, response, error) in
            guard error == nil else  {
                completion(.error(.apiError))
                return
            }
            guard let httpResponse = response as? HTTPURLResponse else {
                print(response)
                return
            }
            guard httpResponse.statusCode == 200 else {
                print(httpResponse.statusCode)
                print(response)
                completion(.error(.badResponse))
                return
            }

            do {
                let dictionaryFromJSON = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [String:Any]

                let jsonItem = dictionaryFromJSON["list"] as? NSArray

                let jsonData = try JSONSerialization.data(withJSONObject: jsonItem!, options: [])

                let responseModel = try JSONDecoder().decode([List].self, from: jsonData as! Data)
                // Error changing line the above [List] to List (comment error 2)

                print(responseModel)
                completion(.value(responseModel))

            }
            catch {
                print("darn")
                print(error)
                completion(.error(.jsonDecoder))
            }
        }
        task.resume()
    }
}

当我打印响应模型时,我有一个包含我想要的数据的有效 json。问题是正确地将其传递给完成。我收到一个编译时错误:"Member 'value' in 'Either' produces result of type 'Either', but context expects 'Either'"

最初错误是有道理的,因为结果类型与预期的上下文不同,但我更改了 api 客户端代码以便它们匹配,但我仍然收到错误。

我删除了括号并在解码调用中使用了一个数组对象来修复代码:

let responseModel = try JSONDecoder().decode([List].self, from: jsonData as! Data)

let responseModel = try JSONDecoder().decode(Array<List>.self, from: jsonData)

然后我从 List 中删除了所有地方的括号并更改了 Either 的枚举定义以使用新的数组格式:case value(Array<List>)

我使用 .

从 JSON 解码行(如上所示)中删除括号时解决了一个中间错误 ("Expected to decode Dictionary but found an array instead.")