如何修复:"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.")
我正在使用 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>)
我使用