GO FURTHER, FASTER: Try the Swift Career Accelerator today! >>

quick question about optional and if

Forums > Swift

Hi, starting to move my objc code to Swift and it's great but for a very old programmer a lot of the optionals, guards and if lets feels very strict :)

To me, the code below is pretty clear, and i actually don't really get why the code doesn't compile since i literally do a null check right before

So I couldn't get this to work without force unwrapping the myLocation after the ||, but for my curiousity, is there another way to get it in one line in kind of the same way? Apparently force unwrapping is so frowned upon so wondering if there's another way to do it without a bunch of extra lines.

code:

let newLocation: CLLocation
.....
let myLocation = CLLocation?

if (myLocation == nil || myLocation!.horizontalAccuracy > newLocation.horizontalAccuracy) {
//do stuff
}

   

Hi,

If I understand your question correctly, I would have used "guard let" in this case even if there will be a couple of extra lines. Then it becomes clear what you want to achieve. (In other cases, nil-coalescing can be smooth, i.e. insert a default value if the variable is nil.)

guard let myLocation = myLocation else {
    // `myLocation` is nil, so do stuff
    return
}

if myLocation.horizontalAccuracy > newLocation.horizontalAccuracy {
    // do stuff
}

Using an if let statement is another safe and idiomatic way to handle optionals in Swift. This approach allows you to unwrap myLocation only if it’s not nil and then perform the comparison. Here’s how you can rewrite the logic using if let:

if let myLocation = myLocation, myLocation.horizontalAccuracy > newLocation.horizontalAccuracy {
    // do stuff
} else {
    // do stuff if myLocation is nil or accuracy is lower
}

   

To me, the code below is pretty clear, and i actually don't really get why the code doesn't compile since i literally do a null check right before

So I couldn't get this to work without force unwrapping the myLocation after the ||

Because even though you've verified that myLocation does not have a nil value, it is still an Optional, so you have to unwrap it to get at the non-nil value within.

This makes more sense once you understand that the Optional type is implemented as an enum of two cases (some and none) with an associated value in the some case:

Simplified implementation of Optional:

enum Optional<Wrapped> {
  case none
  case some(Wrapped)
}

The compiler (at least, I think it's tucked away somewhere in the compiler) has special knowledge of the none case so that we can test for it using = nil or != nil but to get at the value wrapped in the some case you need to do extra work.

So it's not like, say, an Optional Int is either nil or an Int; an Optional Int is actually an Optional that contains either nil or a wrapped Int. And you always have to unwrap an Optional (using one of several ways to do it) to get at the non-nil value stored within. Simply testing that it's not nil only tells you that much; you still have an Optional that you have to dig into.

1      

@roosterboy hey thanks for that explanation didn't know the structure behind.

So, that basically means that the if that looks simple can't be done i guess. I'll have that force unwrapped then, and try to be super conservative of when i force unwrap. Makes sense?

   

@martinatelitappar sure but in my case, i want the "if let... OR myLocation is null" to be the if and otherwise do nothing. Seems there's no way to do that in a neat one-liner. Thanks for pitching in!

   

Hi,

Aha, I see. Yes, it seems you have found a good solution that is simple and clear. There is one more option but I think your option is clearer.

Using Optional Chaining and Nil-Coalescing Operator (One-Liner)

You can combine optional chaining (myLocation?.horizontalAccuracy) with the nil-coalescing operator (??) to handle the case when myLocation is nil. This approach does not require force unwrapping and keeps the logic in one line:

if myLocation?.horizontalAccuracy ?? Double.greatestFiniteMagnitude > newLocation.horizontalAccuracy {
    // do stuff
}

Nil-Coalescing Operator (??): If the left-hand side of the ?? operator is nil, it provides a fallback value. Here, Double.greatestFiniteMagnitude is used as a fallback, representing a very large number. This makes it as though nil means “worst possible accuracy,” hence the condition will likely be true if myLocation is nil.

Thanks for your question, it got me thinking, fun!

1      

Hey Martin again thanks for response. I actually did see a suggestion for that way in some article somewhere, during my 40-day walk in the desert to find a solution :) However i don't like it very much because it feels "hacky" if you see what i mean. Comparing it to the "greatest value" might work but it doesn't "look logical" IMO since that's not really the goal of the check. I'll keep the force unwrap then since it seems we agree :)

1      

Hacking with Swift is sponsored by Alex.

SPONSORED Alex is the iOS & Mac developer’s ultimate AI assistant. It integrates with Xcode, offering a best-in-class Swift coding agent. Generate modern SwiftUI from images. Fast-apply suggestions from Claude 3.5 Sonnet, o3-mini, and DeepSeek R1. Autofix Swift 6 errors and warnings. And so much more. Start your 7-day free trial today!

Try for free!

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

Reply to this topic…

You need to create an account or log in to reply.

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.