The power of guard / let!

Hey everyone! First post. I’m loving the instruction here. JUST FINISHED the iOS Foundations course ––WOOP WOOP!

I want to share something cool I [think] I’m figuring out –– the power of guard and guard-let!

In the City Sights App, we had a gazillion JSON keys to parse and we made them all optional. Sounds like a good call, but causes the annoyance of adding a gazillion+ unwrappings, with prolly a lot of if-let statements, and nested ones. Aye!

This causes at least 2 problems: 1) we have lots of indentation, and code gets harder to read, 2) we have a more limited scope to work with each of the things we’re if-letting. In other words, we can only access the if-let constants (and if-var variables, of course–yeah, you can do dat!) from within the scope of those if-lets / if-vars.

:mechanical_arm: Enter the guard-let statement! :mechanical_arm:

Say we have an optional at Class.property that we need to do something with. Instead of:

if let property = Class.property {  
    // do some stuff with safely unwrapped property
}

We can say:

guard let property = Class.property else { return } 
// do some stuff with safely unwrapped property

See? The // do some stuff with line of code is now outside of the scope of the handling of the optional (I’m forgetting the term for this kind of optional handling…).

Don’t forget––in either the if-let or guard-let, you can add multiple checks, like:

guard let error == nil, let response else { return }
// do some stuff with safely unwrapped response, knowing error == nil

…and like above, if you’re checking a local symbol (without a dot in the name), you don’t even need an equal sign. Also like above, you can mix conditional checks with lets or vars! This also applies to if-let / if-var.

:warning:
You can’t use guard-let anywhere you use if-let, but a lot of places do work. For example, I haven’t been able to use guard statements at all in view structs. In the context of views, our options are if let || if var || ?? || !.

FUN!
3 Likes

What case??

Typically no you can’t, and shouldn’t because you shouldn’t mix that much logic in your view.

It should be somewhere else, a view model maybe, and instead your view handles the right view to show, depending on logic that’s elsewhere

—-
But when to use which is dependent on your code and what it should do!! Not only the scope and indentation, that isn’t inherently a bad thing

Guards make it so that you code must exit when hitting that point, that’s why the else keyword is required. If it’s something your function must have to execute, use a guard, otherwise an if would be better, or using nil coalescing or optional chaining works

A guard shouldn’t be “the end all, be all”

2 Likes

Yes! This is the kind of discussion I was hoping for. Thank you!

To clarify, I didn’t mean to imply that guard let should always be used over if let.

I was actually leaving out the entire notion as I’m still a little fuzzy on when to prefer either, hoping someone like yourself would chime in. Your addition to the thread helps clear that up.

I do dig the benefits of guard let, though – “return early,” maintain access to the symbols outside of the scope of the guard (which leads to less indentation–a bonus). But no, it should not always be chosen over if-let. Thank you for clarifying for folks reading this thread.

There are some cases where you want to check if a value is nil before displaying a view (as I’m sure you know), hence my mention of being unable to use guards in a view. That was the first thing I tried when I discovered guard let, and quickly realized it didn’t make sense to use in the context of a view. Was just making a note for others.