Swift4错误:抛出函数无法转非抛出函数及解码问题求助
解决HTTP响应解码时的函数类型不匹配错误
这个问题我之前也踩过坑,核心原因很明确:URLSession的dataTask回调闭包是不允许抛出错误的,但你在闭包里直接用了带try的解码操作却没做错误捕获,导致编译器认为这个闭包是“抛出函数”,和要求的“非抛出函数”类型不匹配,才会报那个错。
先看你大概率写错的代码(触发错误的示例)
你可能写了类似这样的代码:
URLSession.shared.dataTask(with: requestUrl) { data, response, error in let decoder = JSONDecoder() // 这里直接try却没catch,导致闭包变成抛出类型 let decodedUser = try decoder.decode(User.self, from: data!) // 尝试保存到User属性 self.currentUser = decodedUser }.resume()
正确的解决方式:在闭包内部用do-catch捕获错误
你需要把解码逻辑整个包裹在do-catch块里,把错误“消化”在闭包内部,不让它往外抛。同时还要先处理网络请求本身的错误和空数据的情况,避免崩溃:
URLSession.shared.dataTask(with: requestUrl) { data, response, error in // 1. 先处理网络请求本身的错误 if let requestError = error { print("网络请求失败:\(requestError.localizedDescription)") return } // 2. 确保返回的数据不为空,避免强制解包崩溃 guard let responseData = data else { print("服务器未返回任何数据") return } // 3. 用do-catch包裹解码操作,捕获所有可能的解码错误 do { let decodedUser = try JSONDecoder().decode(User.self, from: responseData) // 4. 把解码后的信息保存到User属性 // 注意:如果要更新UI,必须切回主队列(URLSession回调在后台线程) DispatchQueue.main.async { self.currentUser = decodedUser // 这里可以加UI更新逻辑,比如刷新页面 } } catch let decodingError { print("数据解码失败:\(decodingError)") // 这里可以根据错误类型做针对性处理,比如提示用户数据格式有误 } }.resume()
几个关键注意点:
- 闭包不能抛出错误:URLSession的回调闭包类型是
(Data?, URLResponse?, Error?) -> Void,没有throws修饰,所以任何可能抛出的操作都必须在闭包内部用do-catch处理。 - 不要强制解包:直接用
data!会导致空数据时崩溃,用guard let做安全校验更稳妥。 - 主队列更新UI:URLSession的回调运行在后台队列,如果要更新UI(比如赋值后刷新界面),必须用
DispatchQueue.main.async切回主线程。 - User结构体要符合Codable:别忘了你的
User结构体必须实现Codable协议(或者Decodable,如果只需要解码),否则解码本身也会失败。
内容的提问来源于stack exchange,提问作者Josh Mustafa
相关产品推荐
相关产品推荐

