31

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?

Cristik
  • 30,989
  • 25
  • 91
  • 127
ktzhang
  • 4,069
  • 2
  • 19
  • 18
  • 1
    This question would be better if you asked about a specific situation instead of just "there seems to be confusion". – jtbandes Aug 08 '14 at 03:41

8 Answers8

64

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

jtbandes
  • 115,675
  • 35
  • 233
  • 266
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

valfer
  • 3,545
  • 2
  • 19
  • 24
4

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 :)

Pratyush Pratik
  • 683
  • 7
  • 14
2

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.

Raj Aryan
  • 363
  • 2
  • 15
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 ""
    }
}
Anil Arigela
  • 436
  • 2
  • 8
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
}
marika.daboja
  • 881
  • 13
  • 27
0

Unwrap optionals safely in Swift 5.7 ⛑

Different techniques (in order of preference)

Use the right tool for the job:

  1. Optional chaining
  2. guard let
  3. if let
  4. Nil coalescing operators

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
  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: ??. 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.

New syntax for if let and guard

var x: EnumExample?

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

// We can still explicitly name the `if let` value if we want.
if let value = x {
    print(value.rawValue)
}

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

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

print(x?.rawValue ?? 0) // Unwrap with nil coalescing

NOTE: I also find Optional chaining a clean alternative to unwrapping optionals, and using x != nil sufficient for instances where we only need to check for existence. This is out of scope of the question for unwrapping optionals though.

Pranav Kasetti
  • 8,770
  • 2
  • 50
  • 71
0
There is only seven ways to unwrap an optional in Swift

    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)
}
Rishi jha
  • 51
  • 2
  • 6
  • 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 Dec 21 '22 at 15:32
  • @DSDmark I already added number of way to unwrap optional with code as asked question is how to unwrap optional. – Rishi jha Dec 22 '22 at 05:45