Last active
October 5, 2022 09:19
-
-
Save nmbr73/337ecc98527a822e49b29ff8e6818888 to your computer and use it in GitHub Desktop.
Accessing optionals ... or: What happens when you want to avoid `if (...!=NULL)` in your language π
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// -------------------------------------------------------------------------- | |
// Summary of the (as always) excelent content | |
// of https://www.hackingwithswift.com/100/swiftui/14 | |
// by #HACKINGWITHSWIFT's Paul @twostraws Hudson. | |
// -------------------------------------------------------------------------- | |
enum BadCaptain : Error { | |
case noGood | |
} | |
func goodCaptain(_ captain: String?) throws -> String { | |
guard let captain = captain else { throw BadCaptain.noGood } | |
return captain | |
} | |
func unwrapSomeCaptain() { | |
var captains = [ | |
"Enterprise": "Picard", | |
"Voyager": "Janeway", | |
"Defiant": "Sisko" | |
] | |
if Bool.random() { | |
captains["Serenity"] = "Reynolds" | |
} | |
// --- Optional type: | |
let captainA: String? = captains["Serenity"] | |
type(of: captainA) | |
let captainB: Optional<String> = captainA | |
type(of: captainB) | |
// --- Optional value: | |
let assumedCaptain = captains["Serenity"] // assumedCaptain is `String?` aka `Optional<String>` | |
type(of: assumedCaptain) | |
// --- Unwrap with nil coalescing: | |
let captainCoalesced = captains["Serenity"] ?? "N.N." // captainCoalesced is `String` | |
type(of: captainCoalesced) | |
// --- Provide default to avoid the optional: | |
let captainDefault = captains["Serenity", default: "N.N."] // captainDefault is `String` | |
type(of: captainDefault) | |
// --- Optional chaining: | |
let captainInChains = captains["Serenity"]?.first?.uppercased().lowercased() // captainInChains is `String?` | |
type(of: captainInChains) | |
// --- Optional chaining with nil coalescing: | |
let captainScream = captains["Serenity"]?.uppercased() ?? "N.N." // captainScream is `String` | |
type(of: captainScream) | |
// --- Unwrap: | |
if let captain = captains["Serenity"] { | |
// captain is `String` | |
type(of:captain) | |
} else { | |
// captains["Serenity"] is `nil` and captain does not exist | |
} | |
// --- Unwrap with shadowing: | |
if let assumedCaptain = assumedCaptain { | |
// this assumedCaptain is `String`, shadowing the assumedCaptain from line 36 | |
type(of:assumedCaptain) | |
} else { | |
// assumedCaptain is `nil` and a local assumedCaptain does not exist | |
} | |
// --- Unwrap with shadowing (new in Swift 5.7; not mentoned on Day 14): | |
if let assumedCaptain { | |
// assumedCaptain is `String` | |
type(of:assumedCaptain) | |
} else { | |
// captains["Serenity"] is `nil` | |
} | |
// --- Unwarp multiple optinals, here with shadowing and a condition (not mentioned): | |
if let captain=captains["Serenity"], let assumedCaptain, captain == assumedCaptain { | |
// captain is `String` - the unwrapped version of captains["Serenity"] | |
type(of:captain) | |
// assumedCaptain is `String` - shadowing the String? type assumedCaptain from line 36 | |
type(of:assumedCaptain) | |
} else { | |
// captains["Serenity"] is `nil` or assumedCaptain is `nil`, or their content is not equal | |
} | |
// --- Forced unwrap (not mentioned if I remember correctly): | |
if captains["Serenity"] != nil { | |
// Force unwrap only if you are sure it's not nil! | |
let captain = captains["Serenity"]! | |
// captain is `String` | |
type(of:captain) | |
} else { | |
// captains["Serenity"] is `nil` and captain does not exist | |
} | |
// --- Implicitly unwrapped type (not mentioned if I remember correctly): | |
if captains["Serenity"] != nil { | |
let implicitCaptain: String! | |
// neither force unwrapp nor nil coalescing needed afterwards: | |
implicitCaptain = captains["Serenity"] | |
// implicitCaptain is `String` | |
type(of:implicitCaptain) | |
} else { | |
// captains["Serenity"] is `nil` and captain does not exist | |
} | |
// --- Optional try: | |
if let captain = try? goodCaptain(captains["Serenity"]) { | |
// captain is `String` | |
type(of:captain) | |
} | |
// --- Optional try with nil coalescing: | |
let tryCaptain = (try? goodCaptain(captains["Serenity"])) ?? "N.N." // tryCaptain is `String` | |
type(of: tryCaptain) | |
// --- Guarded: | |
guard let captain = captains["Serenity"] else { | |
// captains["Serenity"] is `nil` and captain dos not exist | |
return | |
} | |
// captain is `String` | |
type(of:captain) | |
// --- Guarded shadowing: | |
guard let assumedCaptain = assumedCaptain else { | |
// captains["Serenity"] is `nil` and assumedCaptain dos not exist | |
return | |
} | |
// assumedCaptain is `String` (remember: assumedCaptain was | |
// a String? in line 36 and so it still was in line 128) | |
type(of:assumedCaptain) | |
} | |
unwrapSomeCaptain() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment