Laurence Wingo
Laurence Wingo

Reputation: 3952

Not using unwrapping in guard statements

I understand the use of optionals enough to know when its necessary to unwrap an optional using the exclamation point. Why is it that the exclamation point isn't needed in a guard statement?

This code works and compiles but doesn't use exclamation points:

struct Blog{

  var author:String?
  var name: String?

}

func blogInfo2(blog:Blog?){
  guard let blog = blog else {
    print("Blog is nil")
    return
  }
  guard let author = blog.author, name = blog.name else {
    print("Author or name is nil")
    return
  }
  print("BLOG:")
  print(" Author: \(author)")
  print(" name: \(name)")
}

This code also works if you do put the exclamation points:

struct Blog{

  var author:String?
  var name: String?

}

func blogInfo2(blog:Blog?){
  guard let blog = blog! else {
    print("Blog is nil")
    return
  }
  guard let author = blog.author!, name = blog.name! else {
    print("Author or name is nil")
    return
  }
  print("BLOG:")
  print(" Author: \(author)")
  print(" name: \(name)")
}

Isn't this a little contradictory or can someone clearly explain why the exclamation point isn't needed?

Upvotes: 0

Views: 546

Answers (3)

Martin Marconcini
Martin Marconcini

Reputation: 27226

I understand the use of optionals enough to know when its necessary to unwrap an optional using the exclamation point.

I have the feeling that you don't understand Swift Optionals enough if you make that assertion.

The contract behind an Optional is that it may or may not be nil; you don't know it and therefore you have to Unwrap it (like opening a box and see what's inside) before you can tell.

The box may be empty (nil Optional) or it may contain a value.

There are very few reasons to use the Forced Unwrap (!). Very Few, and it's generally considered a bad practice in most (but not all) cases.

To continue the analogy, by force unwrapping stuff, you're saying there is something in this box, and I want you to trust me and don't check.

Knowing that an Empty box will crash your application, this is a very dangerous thing to do, considering Optionals were introduced in Swift to protect you from these sort of crashes to begin with.

The if let/guard let statements basically peek inside the box and if there is something, they give it to you, but they also give you the chance to do something else in case the box is empty.

Xcode does force unwrapping when using IBOutlets because by design the contract is that those objects will be available by the time you can use them in your view controller, but unless you're 100% sure a value is not going to be nil then it's almost always better (and future proof) to use a guard statement (or an if).

In my experience, even when you know for sure, it's still safer to toss a guard and forget about the future problems that may arise.

Upvotes: 2

jscs
jscs

Reputation: 64002

guard let unwrapped = optional is an Optional Binding (no link available directly to the correct book section, unfortunately). It safely tries to unwrap the value in the optional. If there is a value, the unwrap succeeds, and the value is assigned to the given name.

You should heavily favor the use of optional bindings, with either guard or if (the difference is the scope of the "unwrapped" name) over the use of forced unwrapping with !. A failed force unwrap is a fatal error; your program will simply crash.

Upvotes: 4

Aaron Brager
Aaron Brager

Reputation: 66244

The exclamation "force" unwraps an optional. guard let or if let unwraps it without forcing anything, so no exclamation point is used.

Upvotes: 1

Related Questions