- Learning Objectives
- Conditionals
- Activity on Conditionals
- Break
- Optionals
- Activity on Optionals
- Wrap Up
By the end of this lesson, students should be able to:
- Use conditional statements in Swift
- Identify and use optionals in Swift code
- Understand the importance of optional binding
- List & apply ways for unwrapping an optional value
Homework review/general questions from last week.
Swift has several constructs to handle control flow in a program.
Using comparison operators and the type Boolean we can manipulate the flow of our apps.
When we have a program and want to tell it to go through a specific path, we evaluate a condition before choosing the path.
- ⏰ Alarm goes off if it's 7:00 am
- 👾 Game ends if time's up
- 📱 Enable dark mode if it's active
This is how we control what happens in our apps.
>= | greater than or equal to |
> | greater than |
<= | less than or equal to |
< | less than |
!= | not equal to |
== | equal to |
&& | and |
The most common way to control the flow of a program.
Allows the program to execute the block only if the condition is true.
let color = "red"
if color == "red"{
print("This is a primary color")
}
Extending the if statement
let color = "purple"
if color == "red" || color == "green" || color == "blue" {
print("This is a primary color")
} else {
print("This is not a primary color")
}
What will print to the console?
var weight = 52
if weight <= 50 {
print("Have a great flight.")
} else {
print("There is a $25 fee for your luggage.")
}
let studentCount = 35
var message = ""
if studentCount < 5 {
message = "Class won't run"
} else if studentCount < 25{
message = "Class will run"
} else if studentCount < 30 {
message = "Class is packed"
} else {
message = "We need another section"
}
print(message)
Sometimes we want to check one condition after another. We use the else-if clause to nest an if statement in the else clause of a previous if statement. The last else clause is optional. We might not always need it.
Having:
let a = 5
let b = 10
var min: Int
var max: Int
Write code that will save the smaller number in min and the greater number in max.
The ternary operator takes a condition and returns one of two values, depending on whether the condition was true or false.
(<CONDITION>) ? <TRUE VALUE> : <FALSE VALUE>
let degrees = 76
let mood = degrees > 70 ? 😊 : 😔
let buttonTitle = isFavorite ? "Remove" : "Save"
Rewrite the min/max if statement with the ternary operator.
“One of the greatest strengths of Swift is its ability to read code and quickly understand data.
When a function may or may not return data, Swift forces you to deal properly with both possible scenarios.
Swift uses unique syntax, called optionals, to handle this sort of case.”
Excerpt From: Apple Education. “Develop in Swift Fundamentals.” Apple Inc. - Education, 2020. Apple Books. Think of an Optional as a box that can only hold a certain type of something.For example a DogBox that can only store a Dog.
The DogBox can only have one of two states: it's empty, or it contains a Dog.
When the box is empty it has a nil value.When the box is not empty, it has some value: a Dog.
Optionals are a special type in Swift.
An optional can represent a value or the absence of a value.
var volunteer : String = "Nadia"
var fosterDog : String = "Lentil"
We need an explicit way to represent the absence of a value. This would be using nil. Swift gives us optionals, that can handle the possibility of a value to be nil.
Handling a non-optional - we're guaranteed to have a value
var fosterDog : String = "Lentil"
Handling an optional - we must handle the nil case
var fosterDog : String? = "Lentil"
var fosterDog : String? = nil
var fosterDog: String? = "Lentil"
print(fosterDog)
Optional("Lentil")
This isn't wrong, but what we want is to get the value out of the box to print it.
We need to unwrap the value. Take it our of the box.
We can force unwrap the value using an exclamation mark.
var fosterDog: String? = "Lentil"
var unwrappedDog = fosterDog!
print("The dog's name is \(unwrappedDog)")
The dog's name is Lentil
What happens if we force unwrap the following?
var fosterDog: String?
print("The dog's name is \(fosterDog!)")
We get this:
Fatal error: Unexpectedly found nil while unwrapping an Optional value
if fosterDog != nil {
print("The dog's name is \(fosterDog!)")
} else {
print("Not fostering right now.")
}
The if statement checks if the optional contains nil. If it's not nil then there's a value we can unwrap.
If we use this method, we'll need to remember to check for nil every time we want to unwrap an optional. There's an easier way to do this.Swift has a feature known as optional binding that lets you access the value inside an optional in a safe way.
if let unwrappedDog = fosterDog {
print("The dog's name is \(unwrappedDog)")
} else {
print("Not fostering right now.")
}
If it's nil then the if statement executes the else block.
if let fosterDog = fosterDog {
print("The dog's name is \(fosterDog)")
} else {
print("Not fostering right now.")
}
It's common practice to name the unwrapped constant or variable with the same name as the optional.
Sometimes you we want to check a condition and only continue executing a function if the condition is true.
Swift has a guard statement that works for those situations.
func buyFood(for fosterDog: String?) {
guard let fosterDog = fosterDog else {
print("Not fostering dogs right now. Don't buy food")
return
}
print("Don't forget to get food for \(fosterDog).")
}
buyFood(for: nil)
buyFood(for: "Lentil")
The happy path is what comes if the condition is true and for readability it will be on the left of the code. Also, anything checked in the guard statement’s condition must be true for the remainder of the function and we can safely use their values.
What if we want default values for those cases where when get nil back?
var dietSelected: String?
if let diet = diet {
print("Buying \(dietSelected)")
} else {
print("Buying raw food")
}
If the value inside the optional is nil, we give a default value called nil-coalescing.
<OPTIONAL VALUE> ?? <DEFAULT VALUE>
var dietSelected: String?
var shoppingItem = dietSelected ?? "raw food"
Q1: How would you declare a double named height
with a value of 4.2 that can be set to nil
at a later date?
Q2: What is the purpose of the following code?
if height != nil {
}
Q3: which of the following code snippets uses VALID optional binding syntax?
if let dogName = owner.dog { }
if dogName = owner.dog { }
if let dogName = owner.dog! { }
if let dogName == owner.dog { }
Q4: In your own words, what is the purpose of guard
?
Q5: What will be returned at the end of the function call?
func calculateResult(a: Int?, b: Int?, c: Int?) -> Int {
guard let aValue = a else { return 0 }
guard let bValue = b else ( return aValue }
guard let cValue = c else {return bValue }
return aValue + bValue + cValue
}
calculateResult(a: 4, b: 8, c: nil)
var title : String
var title: String?
var title: String!
- Find out how you can unwrap several values at the same time to avoid something called pyramid of doom.
- Complete Lab 2 and upload to Gradescope.
- Read the Apple Documentation - optionals section and write down questions from things that are unclear.