Let’s talk about
Optionals
Swift Paris Junior at
1. Introduction 📌
What are optionals?
Usage Example
let users: [Int: String] =
[1: "Johny", 2: "Bernard", 3: "Lucie"]
let user1 = users[1]
let user5 = users[5]
User with id 1?
User with id 5?
Usage Example
let users: [Int: String] =
[1: "Johny", 2: "Bernard", 3: "Lucie"]
let user1 = users[1]
let user5 = users[5]
Optionals = represents either a wrapped value or
the absence of a value
User with id 1?
User with id 5?
let users: [Int: String] =
[1: "Johny", 2: "Bernard", 3: "Lucie"]
let user1 = users[1]
let user5 = users[5]
//Optional(« Johny")
Usage Example
User with id 1?
User with id 5?
let users: [Int: String] =
[1: "Johny", 2: "Bernard", 3: "Lucie"]
let user1 = users[1]
let user5 = users[5]
//Optional(« Johny")
//nil
Usage Example
Declare Optionals
Notation ?
var name: String?
var firstName: String? = "Sonia"
let age: Int? = 12
name = "Dupont"
firstName = nil
var name: String? init(name: String,
firstName: String,
nickname: String?)
func getDateFrom(month: Int,
year: Int) -> Date?
Variables Function’s params
Function’s return types
Declare Optionals
2. Implementation 🛠
What’s behind optional?
Wrapper
public enum Optional<Wrapped> {
case none
case some(Wrapped)
}
❌
📦
Generics
public enum Optional<Wrapped> {
case none
case some(Wrapped)
}
Compatible with primitives and customs types.
Extensions
extension Optional: Equatable where Wrapped: Equatable {
// ...
}
Equatable : Comparison between optional values
Where : Conditional conformance
Wrapped types need to implement Equatable
Naive approach
let name: String? = "Valentine"
let name = Optional.some("Valentine")
let firstName: String?
let firstName = Optional.none
Declaration
Naive approach
func sayHello(to firstName: Optional<String>) {
switch firstName {
case .some(let value):
print("Hello (value)")
case .none:
print("Hello you")
}
}
Access optional
3. Unwrapping 🎁
« See what’s inside »
Safe ✅ Unsafe ✴
Unwrapping techniques
Optional bindings, nil coalescing,
optional chaining…
Force unwrapping, implicitly
unwrapped…
Safe techniques ✅
func sayHello(to name: String?) {
if let name = name {
print("Hello (name)")
} else {
print("Hello you")
}
}
if let
Safe techniques ✅
func sayHello(to name: String?) {
guard let name = name else {
return
}
print("Hello (name)")
}
guard let
Safe techniques ✅
func sayHello(to name: String?) {
guard let name = name else {
return
}
print("Hello (name)")
}
guard let
Safe techniques ✅
func sayHello(to name: String?) {
let helloSuffix = name ?? "you"
print("Hello " + helloSuffix)
}
nil coalescing
Safe techniques ✅
func sayHello(to name: String?) {
if let name = name {
print("Hello (name)")
} else {
print("Hello you")
}
}
func sayHello(to name: String?) {
guard let name = name else {
return
}
print("Hello (name)")
}
if let guard let
nil coalescing
func sayHello(to name: String?) {
let helloSuffix = name ?? "you"
print("Hello " + helloSuffix)
}
Unsafe techniques ✴
func sayHello(to name: String?) {
print("Hello (name!)")
}
force unwrapping
Unsafe techniques ✴
func sayHello(to name: String?) {
print("Hello (name!)")
}
@IBOutlet var usernameTextField: UITextField!
force unwrapping
implicit unwrapping
Safe 👍 Unsafe ☠
Safe vs Unsafe
In theory better in any case!
Limit as much as possible
Some exceptions: Inform compilator,
debug tool…
4. Create Optionals 🖌
Where else are optionals ?
Optional typecast
if let cell = collectionView.dequeueReusableCell(for:
indexPath) as? CZGalleryAlbumViewCell {}
as?
Optional try
guard let jsonData = try? Data(contentsOf:
URL(fileURLWithPath: path))
else {
throw RuntimeError("jsonData failed")
}
try?
Failable initializer
init?(_ description: String)
let one = Int("1")
let two = Int("two")
init?
Failable initializer
init?(_ description: String)
let one = Int("1")
let two = Int("two")
init?
//Optional(1)
//nil
Find the type 🎯
Let’s play together!
Example 1
protocol User {}
struct Admin: User {}
let user: User? = Admin()
let admin = user as? Admin
Type of admin ? Admin? or Admin??
Example 1
protocol User {}
struct Admin: User {}
let user: User? = Admin()
let admin = user as? Admin //Admin?
Type of admin ? Admin? or Admin??
Example 2
enum AccessType {
case read
case write
}
struct Admin {
func grantAccess(to: AccessType)
throws -> [AccessType] {
//...
}
}
let admin: Admin? = Admin()
let adminAccess = try? admin?.grantAccess(to: .read)
Type of adminAccess ? [AccessType]? or [AccessType]??
Example 2
enum AccessType {
case read
case write
}
struct Admin {
func grantAccess(to: AccessType)
throws -> [AccessType] {
//...
}
}
let admin: Admin? = Admin()
let adminAccess = try? admin?.grantAccess(to: .read) //[AccessType]??
Swift 4 and less
Type of adminAccess ? [AccessType]? or [AccessType]??
Example 2
enum AccessType {
case read
case write
}
struct Admin {
func grantAccess(to: AccessType)
throws -> [AccessType] {
//...
}
}
let admin: Admin? = Admin()
let adminAccess = try? admin?.grantAccess(to: .read)
Swift 5
Type of adminAccess ? [AccessType]? or [AccessType]??
//[AccessType]?
Example 3
let users: [String: Int?] = ["theo@gmail.com": 21,
"lucille@gmail.com": 45,
"charles@laposte.net" : nil]
let theoAge = users["theo@gmail.com"]
Type of theoAge ? Int? or Int??
Example 3
let users: [String: Int?] = ["theo@gmail.com": 21,
"lucille@gmail.com": 45,
"charles@laposte.net" : nil]
let theoAge = users["theo@gmail.com"] //Int??
Type of theoAge ? Int? or Int??
5. Transform Optionals 🔮
Map
🧪📤 📥
Unwrap Tranform Wrap
1 2 3
Map
let number: Int? = 10
let square = number.map { $0 * $0 } //Int?
Map
let number: String? = "10"
1. Transform String into Int
2. Square transformation
Map
let number: String? = "10"
let square = number.map { Int($0) }
Map
let number: String? = "10"
let square = number.map { Int($0) }
Unwrap Tranform Wrap
1 2 3
Optional("10")
"10" Optional(10) Optional(
Optional(10))
//Int??
Map
let number: String? = "10"
let square = number.map { Int($0) }?.map { $0 * $0 }
Use flatmap
let number: String? = "10"
let square = number.flatMap { Int($0) }.map { $0 * $0 }
FlatMap
🧪📤 📥
Unwrap Tranform Wrap
1 2 3
Map or FlatMap ?
Transform
closure
Optionals?
Yes
No
Map
FlatMap
Bonus - Extensions 🔥
Pimp your optionals!
Examples
extension Optional {
func notNil() -> Bool {
return self != nil
}
func or(_ defaultValue: Wrapped) -> Wrapped {
return self ?? defaultValue
}
func filter(_ predicate: (Wrapped) -> Bool) -> Wrapped? {
guard let unwrapped = self,
predicate(unwrapped) else { return nil }
return self
}
}
Examples
var score: Int?
let displayedScore = score ?? 0
let displayedScore = score.or(0)
Examples
if let score = score, score > 10 {
print("you win")
} else {
print("you lose")
}
Examples
if let score = score, score > 10 {
print("you win")
} else {
print("you lose")
}
print(score.filter({ $0 > 10 }).notNil()
? "you win" : "you lose")
Thanks!
Optional Questions?
Sources
• The Complete Guide to Optionals in Swift - Paul Hudson
• Optionals in Swift explained: 5 things you should know - Antoine Van Der Lee
• Swift! Optionals? - Sebastian Boldt
• Optionals in Swift: The ultimate guide - Reinder de Vries
• Swift 5.0 is changing optional try - Paul Hudson
• Useful Optional Extensions - Benedikt Terhechte

Optionals Swift - Swift Paris Junior #3

  • 1.
  • 2.
  • 3.
    Usage Example let users:[Int: String] = [1: "Johny", 2: "Bernard", 3: "Lucie"] let user1 = users[1] let user5 = users[5] User with id 1? User with id 5?
  • 4.
    Usage Example let users:[Int: String] = [1: "Johny", 2: "Bernard", 3: "Lucie"] let user1 = users[1] let user5 = users[5] Optionals = represents either a wrapped value or the absence of a value
  • 5.
    User with id1? User with id 5? let users: [Int: String] = [1: "Johny", 2: "Bernard", 3: "Lucie"] let user1 = users[1] let user5 = users[5] //Optional(« Johny") Usage Example
  • 6.
    User with id1? User with id 5? let users: [Int: String] = [1: "Johny", 2: "Bernard", 3: "Lucie"] let user1 = users[1] let user5 = users[5] //Optional(« Johny") //nil Usage Example
  • 7.
    Declare Optionals Notation ? varname: String? var firstName: String? = "Sonia" let age: Int? = 12 name = "Dupont" firstName = nil
  • 8.
    var name: String?init(name: String, firstName: String, nickname: String?) func getDateFrom(month: Int, year: Int) -> Date? Variables Function’s params Function’s return types Declare Optionals
  • 9.
  • 10.
    Wrapper public enum Optional<Wrapped>{ case none case some(Wrapped) } ❌ 📦
  • 11.
    Generics public enum Optional<Wrapped>{ case none case some(Wrapped) } Compatible with primitives and customs types.
  • 12.
    Extensions extension Optional: Equatablewhere Wrapped: Equatable { // ... } Equatable : Comparison between optional values Where : Conditional conformance Wrapped types need to implement Equatable
  • 13.
    Naive approach let name:String? = "Valentine" let name = Optional.some("Valentine") let firstName: String? let firstName = Optional.none Declaration
  • 14.
    Naive approach func sayHello(tofirstName: Optional<String>) { switch firstName { case .some(let value): print("Hello (value)") case .none: print("Hello you") } } Access optional
  • 15.
    3. Unwrapping 🎁 « Seewhat’s inside »
  • 16.
    Safe ✅ Unsafe✴ Unwrapping techniques Optional bindings, nil coalescing, optional chaining… Force unwrapping, implicitly unwrapped…
  • 17.
    Safe techniques ✅ funcsayHello(to name: String?) { if let name = name { print("Hello (name)") } else { print("Hello you") } } if let
  • 18.
    Safe techniques ✅ funcsayHello(to name: String?) { guard let name = name else { return } print("Hello (name)") } guard let
  • 19.
    Safe techniques ✅ funcsayHello(to name: String?) { guard let name = name else { return } print("Hello (name)") } guard let
  • 20.
    Safe techniques ✅ funcsayHello(to name: String?) { let helloSuffix = name ?? "you" print("Hello " + helloSuffix) } nil coalescing
  • 21.
    Safe techniques ✅ funcsayHello(to name: String?) { if let name = name { print("Hello (name)") } else { print("Hello you") } } func sayHello(to name: String?) { guard let name = name else { return } print("Hello (name)") } if let guard let nil coalescing func sayHello(to name: String?) { let helloSuffix = name ?? "you" print("Hello " + helloSuffix) }
  • 22.
    Unsafe techniques ✴ funcsayHello(to name: String?) { print("Hello (name!)") } force unwrapping
  • 23.
    Unsafe techniques ✴ funcsayHello(to name: String?) { print("Hello (name!)") } @IBOutlet var usernameTextField: UITextField! force unwrapping implicit unwrapping
  • 24.
    Safe 👍 Unsafe☠ Safe vs Unsafe In theory better in any case! Limit as much as possible Some exceptions: Inform compilator, debug tool…
  • 25.
    4. Create Optionals🖌 Where else are optionals ?
  • 26.
    Optional typecast if letcell = collectionView.dequeueReusableCell(for: indexPath) as? CZGalleryAlbumViewCell {} as?
  • 27.
    Optional try guard letjsonData = try? Data(contentsOf: URL(fileURLWithPath: path)) else { throw RuntimeError("jsonData failed") } try?
  • 28.
    Failable initializer init?(_ description:String) let one = Int("1") let two = Int("two") init?
  • 29.
    Failable initializer init?(_ description:String) let one = Int("1") let two = Int("two") init? //Optional(1) //nil
  • 30.
    Find the type🎯 Let’s play together!
  • 31.
    Example 1 protocol User{} struct Admin: User {} let user: User? = Admin() let admin = user as? Admin Type of admin ? Admin? or Admin??
  • 32.
    Example 1 protocol User{} struct Admin: User {} let user: User? = Admin() let admin = user as? Admin //Admin? Type of admin ? Admin? or Admin??
  • 33.
    Example 2 enum AccessType{ case read case write } struct Admin { func grantAccess(to: AccessType) throws -> [AccessType] { //... } } let admin: Admin? = Admin() let adminAccess = try? admin?.grantAccess(to: .read) Type of adminAccess ? [AccessType]? or [AccessType]??
  • 34.
    Example 2 enum AccessType{ case read case write } struct Admin { func grantAccess(to: AccessType) throws -> [AccessType] { //... } } let admin: Admin? = Admin() let adminAccess = try? admin?.grantAccess(to: .read) //[AccessType]?? Swift 4 and less Type of adminAccess ? [AccessType]? or [AccessType]??
  • 35.
    Example 2 enum AccessType{ case read case write } struct Admin { func grantAccess(to: AccessType) throws -> [AccessType] { //... } } let admin: Admin? = Admin() let adminAccess = try? admin?.grantAccess(to: .read) Swift 5 Type of adminAccess ? [AccessType]? or [AccessType]?? //[AccessType]?
  • 36.
    Example 3 let users:[String: Int?] = ["theo@gmail.com": 21, "lucille@gmail.com": 45, "charles@laposte.net" : nil] let theoAge = users["theo@gmail.com"] Type of theoAge ? Int? or Int??
  • 37.
    Example 3 let users:[String: Int?] = ["theo@gmail.com": 21, "lucille@gmail.com": 45, "charles@laposte.net" : nil] let theoAge = users["theo@gmail.com"] //Int?? Type of theoAge ? Int? or Int??
  • 38.
  • 39.
  • 40.
    Map let number: Int?= 10 let square = number.map { $0 * $0 } //Int?
  • 41.
    Map let number: String?= "10" 1. Transform String into Int 2. Square transformation
  • 42.
    Map let number: String?= "10" let square = number.map { Int($0) }
  • 43.
    Map let number: String?= "10" let square = number.map { Int($0) } Unwrap Tranform Wrap 1 2 3 Optional("10") "10" Optional(10) Optional( Optional(10)) //Int??
  • 44.
    Map let number: String?= "10" let square = number.map { Int($0) }?.map { $0 * $0 }
  • 45.
    Use flatmap let number:String? = "10" let square = number.flatMap { Int($0) }.map { $0 * $0 }
  • 46.
  • 47.
    Map or FlatMap? Transform closure Optionals? Yes No Map FlatMap
  • 48.
    Bonus - Extensions🔥 Pimp your optionals!
  • 49.
    Examples extension Optional { funcnotNil() -> Bool { return self != nil } func or(_ defaultValue: Wrapped) -> Wrapped { return self ?? defaultValue } func filter(_ predicate: (Wrapped) -> Bool) -> Wrapped? { guard let unwrapped = self, predicate(unwrapped) else { return nil } return self } }
  • 50.
    Examples var score: Int? letdisplayedScore = score ?? 0 let displayedScore = score.or(0)
  • 51.
    Examples if let score= score, score > 10 { print("you win") } else { print("you lose") }
  • 52.
    Examples if let score= score, score > 10 { print("you win") } else { print("you lose") } print(score.filter({ $0 > 10 }).notNil() ? "you win" : "you lose")
  • 53.
  • 54.
    Sources • The CompleteGuide to Optionals in Swift - Paul Hudson • Optionals in Swift explained: 5 things you should know - Antoine Van Der Lee • Swift! Optionals? - Sebastian Boldt • Optionals in Swift: The ultimate guide - Reinder de Vries • Swift 5.0 is changing optional try - Paul Hudson • Useful Optional Extensions - Benedikt Terhechte