【问题标题】:try-catch inside closure -> Invalid conversion from throwing to non-throwing function type闭包内的 try-catch -> 从抛出到非抛出函数类型的无效转换
【发布时间】:2017-12-04 01:31:51
【问题描述】:
我已经用 throws 标记了我的函数,为什么 swift 强制我使用 do-try-catch 块?
我想处理我在下面调用此函数时引发的任何类型的错误。
static func getPosts() throws {
let url = URL(string: "https://jsonplaceholder.typicode.com/posts/1")
let request = URLRequest(url: url!)
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
let json = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableLeaves) as! [String: Any]
}.resume()
}
下面是我遇到的错误的屏幕截图。
【问题讨论】:
标签:
ios
swift
error-handling
try-catch
【解决方案1】:
你的throws 是说你的getPosts() 函数本身会抛出。但是,它在调用闭包之前就完成了,这意味着即使json解析抛出异常,你已经过了可以捕获和处理异常的时间。
闭包中的错误必须在闭包中处理。您正在寻找类似
static func getPosts(completion: @escaping (_ error: String) -> Void) {
let url = URL(string: "https://jsonplaceholder.typicode.com/posts/1")
let request = URLRequest(url: url!)
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
do {
let json = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableLeaves) as! [String: Any]
completion("ok")
}catch let error {
print(error)
completion("error")
}
}.resume()
}
【解决方案2】:
不可能从闭包中捕获错误。
一个合适的解决方案是一个枚举和一个完成处理程序
enum PostResult {
case success([String:Any]), failure(Error)
}
func getPosts(completion:@escaping (PostResult)->() ) {
let url = URL(string: "https://jsonplaceholder.typicode.com/posts/1")!
// no URLRequest needed !
let session = URLSession.shared
session.dataTask(with: url) { (data, response, error) in
if let error = error {
completion(.failure(error))
return
}
do {
let json = try JSONSerialization.jsonObject(with: data!) as! [String: Any]
completion(.success(json))
} catch {
completion(.failure(error))
}
}.resume()
}
并使用它
getPosts { result in
switch result {
case .success(let json): print(json)
// process json
case .failure(let error): print(error)
// handle error
}
}