25

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
  • 28,596
  • 24
  • 84
  • 120
ktzhang
  • 3,879
  • 2
  • 18
  • 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

6 Answers6

61

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

  • 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
  • 110,948
  • 34
  • 232
  • 256
11

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,475
  • 2
  • 17
  • 23
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
  • 653
  • 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
  • 353
  • 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
  • 416
  • 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
  • 699
  • 9
  • 23