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 块处理错误或将它们传播给调用者。

更新于:2023年5月4日

2000+ 次浏览

开启您的职业生涯

完成课程获得认证

开始学习
广告