UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

Unwrapping optionals questions

Forums > 100 Days of SwiftUI

Hi,

I have to use if let only if i know my optional isnt nil and has a value so whats the point of using it? If i know my optional has a value - its not optional right? :) Can i use if let and guard let when i dont know i have a value or not?

another thing: I watched different optionals tutorial and the guy was using if let else which looks like if let and guard let combined. Is it ok to use such if let else or is it older version of Swift? https://www.youtube.com/watch?v=ZL8BFK8bVjk

Thank you!

2      

Yes, you can use if let and guard let with your Optional whether or not you know it actually contains a value. That's the whole point of them, in fact: To find out if an Optional is nil and then do something based on the result.

And yes, if let else is perfectly fine.

func optionalTest(value: Int?) {
    //is value nil? we don't know
    if let value = value {
        print("value is not nil: \(value)")
    } else { //and here is an else clause
        print("value is nil")
    }
}

optionalTest(value: 3)
//value is not nil: 3
optionalTest(value: nil)
//value is nil

2      

Any time you use an optional value, you will have to unwrap it in one way or another. Even if you know for certain that it has a valid value because of the way that you have coded it.

So, if you consider this code...

struct ContentView: View {
    let myNumber: Int? = 1

    var body: some View {
        Text("\(myNumber)")
    }
}

It won't work. Even though we know that we set myNumber equal to 1, and it is a constant (let), so it can not be changed. Swift still tries to be careful because we have declared it as an Int? (optional Int).

So, we have a few options...

We can force unwrap the value with !

struct ContentView: View {
    let myNumber: Int? = 1

    var body: some View {
        Text("\(myNumber!)")
    }
}

But if myNumber actually contains nil in this case, then the program will crash.

We can use if let to unwrap the value

struct ContentView: View {
    let myNumber: Int? = 1

    var body: some View {
        if let myNumber {
            Text("\(myNumber)")
        }
        //possible additional code here
    }
}

In this case, if myNumber contains nil then the entire if let myNumber { ... } block of code is just skipped. So no Text view would be shown in ContentView and nothing else would be done.

(If we included any additional code after the end of the if closure it would still be run.)

We can use guard let to unwrap the value

struct ContentView: View {
    let myNumber: Int? = nil

    var body: some View {
        guard let myNumber else { return Text("No value found") }
        return Text("\(myNumber)")
    }
}

In this case, if myNumber contains nil then a Text view containing "No value found" would be shown instead of the value of myNumber. We would immediately return from the body closure as soon as the guard condition is false. So, any code after the guard line will be completely ignored.

(The else closure and the code that comes after it must both return some View to keep the body property satisfied.)

Try chaging the line

let myNumber: Int? = 1

to

let myNumber: Int? = nil

in each of the examples above, and run the code to see what different results you get.

But yes, you can use if let myNumber { } else { } as well, and it could work almost the same way as guard let myNumber would. But notice that the if let option does not use the return keyword.

struct ContentView: View {
    let myNumber: Int? = nil

    var body: some View {
        if let myNumber {
            Text("\(myNumber)")
        } else {
            Text("No value found")
        }
        //possible additional code here
    }
}

So, in this case, any code included after the if/else closures would still be run, but any code included after the guard would not.

Note: We used to have to write let myNumber = myNumber when unwrapping optionals, but now we can just write let myNumber

2      

P.S. - @roosterboy I keep trying to write responses to people, and then by the time I have finished writing them, you have already responded. I hope that you don't take it as me thinking that your responses are not good enough, and trying to write a better one. I just haven't seen your responses yet before I post mine. But you have probably helped me in these forums more than anyone else in the past. So, thanks for all you do in trying to answer people's questions!

2      

TAKE YOUR SKILLS TO THE NEXT LEVEL If you like Hacking with Swift, you'll love Hacking with Swift+ – it's my premium service where you can learn advanced Swift and SwiftUI, functional programming, algorithms, and more. Plus it comes with stacks of benefits, including monthly live streams, downloadable projects, a 20% discount on all books, and free gifts!

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.