try, try! & try? what’s the difference, and when to use each?

后端 未结 1 1707
傲寒
傲寒 2020-11-30 16:28

In Swift 2.0, Apple introduced a new way to handle errors (do-try-catch). And few days ago in Beta 6 an even newer keyword was introduced (try?). Also, knew tha

相关标签:
1条回答
  • 2020-11-30 16:53

    Updated for Swift 5.1

    Assume the following throwing function:

    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)
      }
    }
    

    try

    You have 2 options when you try calling a function that may throw.

    You can take responsibility of handling errors by surrounding your call within a do-catch block:

    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)
    }
    

    Or just try calling the function, and pass the error along to the next caller in the call chain:

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

    try!

    What happens when you try to access an implicitly unwrapped optional with a nil inside it? Yes, true, the app will CRASH! Same goes with try! it basically ignores the error chain, and declares a “do or die” situation. If the called function didn’t throw any errors, everything goes fine. But if it failed and threw an error, your application will simply crash.

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

    try?

    A new keyword that was introduced in Xcode 7 beta 6. It returns an optional that unwraps successful values, and catches error by returning nil.

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

    Or we can use guard:

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

    One final note here, by using try? note that you’re discarding the error that took place, as it’s translated to a nil. Use try? when you’re focusing more on successes and failure, not on why things failed.

    Using Coalescing Operator ??

    You can use the coalescing operator ?? with try? to provide a default value incase of failure:

    let result = (try? doSomething()) ?? "Default Value"
    print(result) // Default Value
    
    0 讨论(0)
提交回复
热议问题