Swift:调用可能抛出异常,但未标记为“try”,也没有处理错误
在 Swift 中,当您调用一个可能抛出错误的函数时,必须使用 try 关键字标记函数调用,或者使用 do-catch 块处理错误。
如果您看到错误消息“Call can throw, but it is not marked with 'try' and the error is not handled”,则表示您调用了可能抛出错误的函数,但您没有正确处理该错误。
如何修复这些错误?
使用 try 关键字标记函数调用。例如:
do { let result = try someFunctionThatCanThrow() // Handle the result } catch { // Handle the error }
使用 do-catch 块处理错误。例如:
do { let result = someFunctionThatCanThrow() // Handle the result } catch { // Handle the error }
无论哪种情况,都需要处理错误以确保代码的健壮性并能够处理意外情况。
示例 1
考虑一个名为 divide 的函数,它接收两个数字作为输入,并返回第一个数字除以第二个数字的结果。但是,如果第二个数字为零,则该函数会抛出错误。
import Foundation func divide(_ dividend: Int, by divisor: Int) throws -> Int { guard divisor != 0 else { throw NSError(domain: "com.example", code: 0, userInfo: [ NSLocalizedDescriptionKey: "Cannot divide by zero" ]) } return dividend / divisor }
在这个例子中,我们用 throws 关键字标记了该函数,以表明它可能抛出错误。如果除数输入为零,则函数会抛出错误。
现在,假设我们这样调用 divide 函数:
let result = divide(10, by: 0)
这段代码将导致以下错误消息:
error: call can throw but is not marked with 'try' let result = divide(10, by: 0)
错误消息告诉我们,divide 函数可能抛出错误,但我们既没有使用 try 标记函数调用,也没有处理错误。
我们可以通过这种方式修复此错误消息:
import Foundation func divide(_ dividend: Int, by divisor: Int) throws -> Int { guard divisor != 0 else { throw NSError(domain: "com.example", code: 0, userInfo: [ NSLocalizedDescriptionKey: "Cannot divide by zero" ]) } return dividend / divisor } do { let result = try divide(10, by: 0) print(result) } catch let err { print("Error found: \(err)") }
输出
Error found: Error Domain=com.example Code=0 "(null)"
这将捕获 divide 函数抛出的错误并执行 catch 块。
示例 2
在这个例子中,我们想将文件的内容读取到一个字符串中。我们使用 String(contentsOf:encoding:) 初始化器来读取文件。但是,如果找不到文件或无法读取文件,则此初始化器可能会抛出错误。
let filename = "example.txt" let contents = String(contentsOfFile: filename, encoding: .utf8) print(contents)
这段代码将导致错误消息“Call can throw, but it is not marked with 'try' and the error is not handled”。要修复此错误,我们可以使用 try 标记初始化器或使用 do-catch 块处理错误。
import Foundation let filename = "example.txt" do { let contents = try String(contentsOfFile: filename, encoding: .utf8) print(contents) } catch { print(error.localizedDescription) }
输出
The operation could not be completed. No such file or directory
示例 3
在这个例子中,我们想从 web 服务解析 JSON 数据。我们使用 JSONSerialization.jsonObject(with:options:) 方法来解析 JSON 数据。但是,如果数据不是有效的 JSON,则此方法可能会抛出错误。
let data = Data() // JSON data from web service let json = try JSONSerialization.jsonObject(with: data, options: []) print(json)
这段代码将导致错误消息“Call can throw, but it is not marked with 'try' and the error is not handled”。要修复此错误,我们可以使用 try 标记方法或使用 do-catch 块处理错误。
解决方案:
import Foundation let data = Data() // JSON data from web service do { let json = try JSONSerialization.jsonObject(with: data, options: []) print(json) } catch { print(error.localizedDescription) }
输出
这是将打印到控制台的消息:
The operation could not be completed. The data is not in the correct format.
结论
在 Swift 中,可以使用 throws 关键字标记函数或方法以指示它可能抛出错误。调用此类函数或方法时,需要使用 try 标记调用或使用 do-catch 块处理错误。
如果在不使用 try 或处理错误的情况下调用可能抛出错误的函数或方法,Swift 将生成一个编译时错误,其消息为“Call can throw, but it is not marked with 'try' and the error is not handled”。
正确处理错误对于确保代码的健壮性和能够处理意外情况非常重要。如果在当前级别无法处理错误,则应始终使用 do-catch 块处理错误或将它们传播给调用者。