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

ID : 20439

viewed : 41

Tags : swifterror-handlingswift3swift2swift

Top 5 Answer for swift - try, try! & try? what’s the difference, and when to use each?

vote vote

91

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 
vote vote

80

vote vote

73

To do this without the leading space, why not:

wc -l < file.txt | bc 
vote vote

68

How about

wc -l file.txt | cut -d' ' -f1 

i.e. pipe the output of wc into cut (where delimiters are spaces and pick just the first field)

vote vote

59

Comparison of Techniques

I had a similar issue attempting to get a character count without the leading whitespace provided by wc, which led me to this page. After trying out the answers here, the following are the results from my personal testing on Mac (BSD Bash). Again, this is for character count; for line count you'd do wc -l. echo -n omits the trailing line break.

FOO="bar" echo -n "$FOO" | wc -c                          # "       3"    (x) echo -n "$FOO" | wc -c | bc                     # "3"           (√) echo -n "$FOO" | wc -c | tr -d ' '              # "3"           (√) echo -n "$FOO" | wc -c | awk '{print $1}'       # "3"           (√) echo -n "$FOO" | wc -c | cut -d ' ' -f1         # "" for -f < 8 (x) echo -n "$FOO" | wc -c | cut -d ' ' -f8         # "3"           (√) echo -n "$FOO" | wc -c | perl -pe 's/^\s+//'    # "3"           (√) echo -n "$FOO" | wc -c | grep -ch '^'           # "1"           (x) echo $( printf '%s' "$FOO" | wc -c )            # "3"           (√) 

I wouldn't rely on the cut -f* method in general since it requires that you know the exact number of leading spaces that any given output may have. And the grep one works for counting lines, but not characters.

bc is the most concise, and awk and perl seem a bit overkill, but they should all be relatively fast and portable enough.

Also note that some of these can be adapted to trim surrounding whitespace from general strings, as well (along with echo `echo $FOO`, another neat trick).

Top 3 video Explaining swift - try, try! & try? what’s the difference, and when to use each?

Related QUESTION?