I've seen this code on the Swift site and various posts here and I am trying to grasp the basics. How is this line evaluated?
if let name = optionalName {
I'm confused as it's not name == optional name, it's assigning the value, so how does that report true and why is it not true when you replace with john appleseed with nil, as its still going to be equal?
var optionalName: String? = "John Appleseed" var greeting = "Hello!" if let name = optionalName { greeting = "Hello, \(name)" }
The “if let” allows us to unwrap optional values safely only when there is a value, and if not, the code block will not run. Simply put, its focus is on the “true” condition when a value exists.
In if let , the defined let variables are available within the scope of that if condition but not in else condition or even below that. In guard let , the defined let variables are not available in the else condition but after that, it's available throughout till the function ends or anything.
Swift employs the keywords let and var for naming variables. The let keyword declares a constant, meaning that it cannot be re-assigned after it's been created (though its variable properties can be altered later). The var keyword declares a new variable, meaning that the value it holds can be changed at a later time.
If a given tag in the JSON data is missing, you'd set that property to nil. You use a constant because the value is fixed once the response object is initialized. If it's nil, it will be nil forever. If it contains a value, it will always contain that value and it can't be changed.
Essentially the line is saying, "if you can let the new variable name
equal the non-optional version of optionalName
, do the following with it". As Martin pointed out, this is called Optional Binding.
The sole purpose of it is to test if an optional variable contains an actual value and bind the non-optional form to a temporary variable. This is the safe way to "unwrap" an optional or in other words, access the value contained in the optional. It is in no way testing for equality of any kind. It is only testing for the existence of a value within an optional.
An optional is either set or not-set (not nil or nil)...leaving us with an important decision. "How should we write our code so that it can work correctly for 2 both states?". The way we unwrap the optional is what decides that for us.
There are several approaches that you can use to counter a not-set optional.
Below are the 4 approaches
Using forced unwrapping will crash if you don't have a value. You would want to do this if having that value is of vital importance e.g. the title of a movie (every movie MUST have a name) . !
is used for forced unwrapping.
movieTitle = movie.title!
Using nil coalescing is another way that will give you more control, meaning it won't crash if the value isn't set, nor it would 'not set it nothing' if it's not set...it would do what you tell it to do e.g. it would default/set the name of movie to untitled_movie if there was no name set. ??
is used for nil coalescing.
var movieTitle = movie.title ?? "untitled_Movie"
Using optional Chaining will do nothing if you don't have a value, and will set the value if you have a value. You do this for something that having its value set is not of vital importance e.g. for the name of your actor's agent.?
is used for optional chaining.
let agent = movie.leadActor?.agent //would not crash if you don't have a lead actor (optional chaining) let agent = movie.leadActor!.agent //would crash if you don't have a lead Actor (forced wrapping)
Using if-let
( or guard
which are two different types of optional binding) will give you more control, it won't crash if the value isn't set. If the value is set, then you can do something. If it's not set then you can add an else
statement.
if let supportingActor = movie.supportingActor{ print(" The supporting actor is \(supportingActor)}
This is the most commonly used way of unwrapping, as forced unwrapping is somewhat discouraged. For more discussion on why it is discouraged see here. For a good comparison between guard
and if-let
see guard vs. if-let
Side note:
Optional binding and optional chaining are commonly used together:
if let agent = movie.leadActor?.agent { ContactInfo = agent.phoneNumber } // if-let is the optional *binding* part, the movie dot leadActor dot is the optional *chaining*
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With