试试!和尝试?有什么区别,以及何时使用它们?


171

Swift 2.0中,Apple引入了一种处理错误的新方法(do-try-catch)。几天前,在Beta 6中,甚至引入了一个更新的关键字(try?)。另外,知道我可以使用try!。这3个关键字之间有什么区别,何时使用每个关键字?

Answers:


316

已为Swift 5.1更新

假定以下抛出函数:

enum ThrowableError: Error {

    case badError(howBad: Int)
}

func doSomething(everythingIsFine: Bool = false) throws -> String {

  if everythingIsFine {
      return "Everything is ok"
  } else {
      throw ThrowableError.badError(howBad: 4)
  }
}

尝试

当您尝试调用可能抛出的函数时,有2个选项。

您可以通过将呼叫围绕在do-catch块中来承担处理错误的责任:

do {
    let result = try doSomething()
}
catch ThrowableError.badError(let howBad) {
    // Here you know about the error
    // Feel free to handle or to re-throw

    // 1. Handle
    print("Bad Error (How Bad Level: \(howBad)")

    // 2. Re-throw
    throw ThrowableError.badError(howBad: howBad)
}

或者只是尝试调用该函数,然后将错误传递给调用链中的下一个调用者:

func doSomeOtherThing() throws -> Void {    
    // Not within a do-catch block.
    // Any errors will be re-thrown to callers.
    let result = try doSomething()
}

尝试!

当您尝试访问其中包含nil的隐式展开的可选内容时会发生什么?是的,的确如此,该应用程序将崩溃!尝试也一样!它基本上会忽略错误链,并声明“行将成灾”的情况。如果被调用的函数没有引发任何错误,则一切正常。但是,如果失败并抛出错误,则您的应用程序将完全崩溃

let result = try! doSomething() // if an error was thrown, CRASH!

尝试?

Xcode 7 beta 6中引入了一个新关键字。它返回一个可选的关键字,该关键字解开成功的值,并通过返回nil捕获错误。

if let result = try? doSomething() {
    // doSomething succeeded, and result is unwrapped.
} else {
    // Ouch, doSomething() threw an error.
}

或者我们可以使用守卫:

guard let result = try? doSomething() else {
    // Ouch, doSomething() threw an error.
}
// doSomething succeeded, and result is unwrapped.

最后一点,通过使用try?注释,您将丢弃发生的错误,因为该错误被转换为nil。使用尝试?当您更多地关注成功和失败时,而不是失败的原因上。

使用合并运算符

您可以使用合并运算符?? 尝试一下?在出现故障时提供默认值:

let result = (try? doSomething()) ?? "Default Value"
print(result) // Default Value

您的第二个代码示例(let result = try doSomething() // Not within a do-catch block)将在声明为的方法中调用throws,对吗?那么,如果doSomething()失败了,外部方法也是如此(反过来)吗?
Nicolas Miari

旧线程和所有线程,但我发现今天(Swift 4,Xcode 9.1)尝试了吗?不会自动解包结果。它只是将其作为常规的可选选项供您手动打开。不知道自Swift 2/3以来这是否发生了变化,但是否符合以下文档:developer.apple.com/library/content/documentation/Swift/…(请参阅将错误转换为可选值)。尝试btw的绝佳解释。
the_dude_abides

1
快速4,尝试?不会删除项目中“ try”表达式中不发生对throw函数的调用。
aznelite89

7
您也可以使用try?with,??因此它可以让您在一行中定义默认值:let something:String = (try? whateverIfItThrows()) ?? "Your default value here"
itMaxence
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.