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 that I can use try!
.
What's the difference between the 3 keywords, and when to use each?

- 30,560
- 17
- 97
- 143

- 6,306
- 3
- 19
- 20
1 Answers
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

- 6,306
- 3
- 19
- 20
-
Your second code sample (`let result = try doSomething() // Not within a do-catch block`) is to be called from within a method that is declared as `throws`, right? So, if `doSomething()` fails, so does the outer method too (in turn)? – Nicolas Miari Sep 04 '15 at 05:24
-
Old thread and all but I found that today (Swift 4, Xcode 9.1) try? doesn't auto-unwrap the result. It just leaves it as a normal optional for you to unwrap manually. Not sure if this changed since Swift 2/3 but it is per the docs: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html (see _Converting Errors to Optional Values_). Great explanation of try btw. – the_dude_abides Nov 27 '17 at 23:56
-
1in swift 4, try? does not remove the no calls to throwing functions occur within 'try' expressions in my project. – aznelite89 Dec 19 '17 at 08:48
-
8You could also use `try?` with `??` so it would let you define a default value in one line: `let something:String = (try? whateverIfItThrows()) ?? "Your default value here"` – itMaxence Jul 26 '18 at 21:09
-
1Does anyone have trouble remembering try! vs try? vs try, and end up here, time and time again... It might be a sign the language is bloated – Ben Butterworth Oct 14 '20 at 09:56
-
2@BenButterworth Honestly not, so long as you remember that only `try` must be enclosed in a do-catch and the other two not, you can then recognise that `!` and `?` work as standard optional operators. – Leon Feb 18 '21 at 17:42