捕获模式更改回调签名
我试图使用JSONDecoder
来解码从我的服务器使用Alamofire json响应。当我用guard
解码响应时,它没有任何问题。这种方法的副作用是我无法分辨解码实际上失败时的问题。捕获模式更改回调签名
guard let result: TResponseData = try? decoder.decode(TResponseData.self, from: response.data!) else {
self.logger.error("Unable to decode the response data into a model representation.")
return
}
所以不是我想要用do { } catch { }
,但我想不出我应该如何准确的Alamofire responseJSON
回调中使用它。
这就是我目前有:
Alamofire.request(completeUrl, method: .post, parameters: parameters, encoding: encoding, headers: headers)
.validate()
.responseJSON { (response) -> Void in
self.logger.info("POST Response: \(String(describing:response.response?.statusCode))")
switch response.result {
case .success(_):
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .custom(Date.toTMDBDate)
do {
let _ = try decoder.decode(TResponseData.self, from: response.data!)
} catch DecodingError.dataCorrupted(let error) {
self.logger.error(error.underlyingError)
return
}
completion(result)
return
case .failure(let error):
//....
}
我这个代码给然而什么是对.responseJSON { (response) -> Void in
行编译错误。
将类型为'(_) - > Void'的投掷函数转换为非抛出函数类型'(DataResponse) - > Void'无效转换。
警卫代码工作正常,如果我改变try
到try?
或强制拆开包装,它编译 - 我只是不明白这有我的捕捉处理实际的错误。
如果我更改catch
块,以便它不包含任何模式,则代码将进行编译。
catch {
return
}
这并不能告诉我什么,我的guard
给了我什么。我真的想要捕获decode
操作遇到的错误。我是否使用了错误的模式?为什么使用DecodingError.dataCorrupted
模式似乎会改变回调签名?
JSONDecoder
可以抛出除DecodingError.dataCorrupted
以外的错误;你需要能够处理被抛出的任意Error
的情况。所以,如果你想处理这个错误,你需要一个无条件的catch {}
块。
你还可以:
- 使用
responseData
而不是responseJSON
当您与JSONDecoder
做你自己deserialisation。 - 如果需要,请在Alamofire的
Result
类型上使用unwrap()
方法,以便将网络错误与解码错误合并。
这是什么样子:
Alamofire
.request(
completeUrl, method: .post, parameters: parameters,
encoding: encoding, headers: headers
)
.validate()
.responseData { response in
self.logger.info(
"POST Response: \(response.response?.statusCode as Any)"
)
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .custom(Date.toTMDBDate)
do {
let result = try decoder.decode(
TResponseData.self, from: response.result.unwrap()
)
completion(result)
} catch {
self.logger.error(error)
}
}
尽管这里有一点要注意的是,你不打电话completion
如果请求失败;我会亲自改变这种做法,并通过使completion
参数为Result<TResponseData>
来传播错误。
在这种情况下,你可以使用Result
的flatMap(_:)
方法,而不是unwrap()
和catch {}
块:
func doRequest(_ completion: @escaping (Result<TResponseData>) -> Void) {
let completeURL = // ...
let parameters = // ...
let encoding = // ...
let headers = // ...
Alamofire
.request(
completeURL, method: .post, parameters: parameters,
encoding: encoding, headers: headers
)
.validate()
.responseData { response in
self.logger.info(
"POST Response: \(response.response?.statusCode as Any)"
)
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .custom(Date.toTMDBDate)
// if response.result is successful data, try to decode.
// if decoding fails, result is that error.
// if response.result is failure, result is that error.
let result = response.result.flatMap {
try decoder.decode(TResponseData.self, from: $0)
}
.ifFailure {
self.logger.error($0)
}
completion(result)
}
}
真棒谢谢! –
嗨,@哈米什,你为什么不把这个作为答案来写,所以约翰逊可以将它标记为这样! – leanne
@leanne现在就完成了:) – Hamish