36

How do you properly unwrap both normal and implicit optionals?

There seems to be confusion in this topic and I would just like to have a reference for all of the ways and how they are useful.

There are currently two ways to create optionals:

var optionalString: String?

var implicitOptionalString: String!

What are all the ways to unwrap both? Also, what is the difference between using ! and ? during the unwrapping?

1
  • 1
    This question would be better if you asked about a specific situation instead of just "there seems to be confusion". Commented Aug 8, 2014 at 3:41

9 Answers 9

74

There are many similarities and just a handful of differences.

(Regular) Optionals

  • Declaration: var opt: Type?

  • Unsafely unwrapping: let x = opt!.property // error if opt is nil

  • Safely testing existence : if opt != nil { ... someFunc(opt!) ... } // no error

  • Safely unwrapping via binding: if let x = opt { ... someFunc(x) ... } // no error

    • Using new shorthand: if let opt { ... someFunc(opt) ... } // no error
  • Safely chaining: var x = opt?.property // x is also Optional, by extension

  • Safely coalescing nil values: var x = opt ?? nonOpt

Implicitly Unwrapped Optionals

  • Declaration: var opt: Type!

  • Unsafely unwrapping (implicit): let x = opt.property // error if opt is nil

    • Unsafely unwrapping via assignment:
      let nonOpt: Type = opt // error if opt is nil

    • Unsafely unwrapping via parameter passing:
      func someFunc(nonOpt: Type) ... someFunc(opt) // error if opt is nil

  • Safely testing existence: if opt != nil { ... someFunc(opt) ... } // no error

  • Safely chaining: var x = opt?.property // x is also Optional, by extension

  • Safely coalescing nil values: var x = opt ?? nonOpt

Sign up to request clarification or add additional context in comments.

Comments

13

Since Beta 5 we have also the new coalescing operator (??):

var a : Int?
let b : Int = a ?? 0

If the optional is != nil it is unwrapped else the value on the right of the operator is used

Comments

3

I created an approach to unwrap optional value:

// MARK: - Modules
import Foundation
import UIKit
import CoreData

// MARK: - PROTOCOL
protocol OptionalType { init() }

// MARK: - EXTENSIONS
extension String: OptionalType {}
extension Int: OptionalType {}
extension Double: OptionalType {}
extension Bool: OptionalType {}
extension Float: OptionalType {}
extension CGFloat: OptionalType {}
extension CGRect: OptionalType {}
extension UIImage: OptionalType {}
extension IndexPath: OptionalType {}
extension Date: OptionalType {}
extension UIFont: OptionalType {}
extension UIColor: OptionalType {}
extension UIViewController: OptionalType {}
extension UIView: OptionalType {}
extension NSMutableDictionary: OptionalType {}
extension NSMutableArray: OptionalType {}
extension NSMutableSet: OptionalType {}
extension NSEntityDescription: OptionalType {}
extension Int64: OptionalType {}
extension CGPoint: OptionalType {}
extension Data: OptionalType {}
extension NSManagedObjectContext: OptionalType {}

prefix operator ?*

//unwrapping values
prefix func ?*<T: OptionalType>( value: T?) -> T {
    guard let validValue = value else { return T() }
    return validValue
}

You can add your custom data type also.

Usage:-

var myString = ?*str

Hope it helps :)

5 Comments

Let alone being the best approach. This is wrong in many ways.
Can you elaborate how? @Desdenova
To start with, take integer for instance, 0 != nil
In both the cases it will return true. You can dry run it.
Is that the required to use an operator? Coming from C#, I have a sinking feeling that I'll never fully grasp Swift's loopy syntax. It's kinda functional, kinda procedural and kinda object-oriented all mixed up. As much as I despise JS, its predatory syntax is far simpler.
2

Unwrap optionals safely in Swift 5.7 ⛑

Different techniques (in order of preference)

Use the right tool for the job:

  1. No Unwrap e.g. optional chaining
  2. guard let
  3. if let
  4. Nil coalescing operators
  5. Force Unwrap

Considerations

There are many ways to unwrap optional values safely in Swift. My reasons for ordering the techniques in my preferences above:

  1. We should only unwrap optionals if we truly need to. In this case, we don't need to unwrap it and can use optional chaining. e.g. let value = optional?.value. Using x != nil may also be sufficient for instances where we only need to check for existence. This is important to consider whether unwrapping optionals is truly needed.
  2. Guard statements are helpful to exit the flow early when there's a precondition. It's the cleanest solution in many cases by reducing the levels of nesting.
  3. if let may be more readable for sequential logic. In some cases, if let is more readable than guards when we don't want to exit a function but continue with additional logic outside the unwrapping block. if let is flexible and can also be used with similar syntax as guard statements.
  4. We can use multiple guard statements to unwrap multiple optionals before using them, or even use ,, && or || to check multiple conditionals in a single guard.
  5. Nil coalescing operators work well to cleanly unwrap optionals with a default value: ??. If the optional is nil it will be set to the default value. Don't overuse them though because using a guard is often clearer to exit early.
  6. I've outlined the improved syntax for if let and guard let (much cleaner in Swift 5.7).
  7. Force unwrapping or IUOs (Implicity Unwrapped Optionals) can lead to runtime crashes. They are indicated by a ! and are an anti-pattern in iOS unless part of a tests suite because they can crash if the optional is nil. In this case, we aren't leveraging Swift's improved type system over Objective-C. In tests, we don't care about clean code because the tests won't run in production and their purpose is contained.

Code examples with new syntax for if let and guard

No Unwrap

print(x?.rawValue)

guard x != nil || y != nil else {
    return
}

if let

We can still explicitly name the if let value if we want. You can emulate the behaviour of a guard in some cases using a return statement too.

var x: EnumExample?

if let x {
   print(x.rawValue) // No longer optional
}

if let value = x {
    print(value.rawValue)
}

if let x {
    print(x.rawValue) // No longer optional
    return
}

guard let

Code shows combining two statements with ,, && or || in a single guard example. You can also use a custom name for unwrapping x with a guard.

guard let x else {
    return
}
print(x.rawValue) // No longer optional

guard let x, x.rawValue > 3 else {
    return
}

guard let value = x else {
    return
}
print(value.rawValue)

Nil coalescing operator ??

print(x?.rawValue ?? 0)

Force unwrap

Using force unwraps is strongly discouraged, and includes Implicitly Unwrapped Optionals that are variables declared with a force unwrap as the type. These can have a value of nil even though they're optional. It can be acceptable to use these in unit tests however for easier testing purposes.

print(x!.rawValue)

var implicitUnwrap: Int!

1 Comment

It'd be better to format explanatory text as normal text, not as code. Yes, you've set it off with comments, but there's no compiler here -- you can use plain text. Also, the latter part about if/guard is only tangentially related to unwrapping and not really responsive to OP's (very old) question.
1

An optional type means that the variable might be nil.

Example:

var myString: Int? = 55
myString = nil

The question mark indicates it might have nil value.

But if you state like this:

var myString : Int = 55
myString = nil

It will show error.

Now to retrieve the value you need to unwrap it:

print(myString!)

But if you want to unwrap automatically:

var myString: Int! = 55

Then:

print(myString)

No need to unwrap. Hope it will help.

Comments

1

There is only seven ways to unwrap an optional in Swift. Assuming:

var x : String? = "Test"
  1. Forced unwrapping — unsafe.

     let a:String = x!
    
  2. Implicitly unwrapped variable declaration — unsafe in many cases.

     var a = x!
    
  3. Optional binding — safe.

    if let a = x {
        print("x was successfully unwrapped and is = \(a)")
    }
    
  4. Optional chaining — safe.

    let a = x?.count
    
  5. Nil coalescing operator — safe.

    let a = x ?? ""
    
  6. Guard statement — safe.

     guard let a = x else {
         return
     }
    
  7. Optional pattern — safe.

     if case let a? = x {
         print(a)
     }
    

2 Comments

It's important to not just post code, but to also include a description of what the code does and why you are suggesting it. This helps others understand the context and purpose of the code, and makes it more useful for others who may be reading the question or answer, @Rishi jha .
@DSDmark I already added number of way to unwrap optional with code as asked question is how to unwrap optional.
1

One thing that I don't see mentioned in any of the existing answers here is that when unwrapping a variable, you don't have to use let with if or guard even though if let and guard let are often presented as the way to unwrap. As always in Swift, using let is appropriate for immutable values, and var is appropriate for mutable values. So, given:

let x: String? = "foo"

You can unwrap using if let if you don't plan to change the value:

if let x {
    print(x)
}

But you can also use if var if you'd like to modify the value:

if var x {
    print(x)     // prints "foo"
    x = "bar"
    print(x)     // prints "bar"
}

Of course, x is a different variable inside the body of the if statement, one that shadows the original x, and any changes that you make apply only to the copy in that shadow variable — if we add a print(x) after the closing } above, Swift will warn about implicitly converting String? to Any, but it will still print Optional("foo") as the value, so the let in the original declaration isn't violated.

The same is true for guard -- you can use guard var in cases where you'd like to be able to change your copy of the value.

Let's stop thinking of if let and guard let as magic formulae for unwrapping variables and instead know that if and guard can be used to unwrap an optional by assigning it to a new variable in the conditional's test.

Comments

0

You can also create extensions for particular type and unwrap safely with default value. I did the following for the same :

extension Optional where Wrapped == String {
    func unwrapSafely() -> String {
        if let value = self {
            return value
        }
        return ""
    }
}

Comments

0

Code sample of Safely unwrapping using binding:

let accountNumber = account.accountNumber //optional
let accountBsb = account.branchCode //optional
var accountDetails: String = "" //non-optional

if let bsbString = account.branchCode, let accString = account.accountNumber {
    accountDetails = "\(bsbString) \(accString)" //non-optional
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.