Optionals by Matt Faluotico

35
var, let, & ? Optionals & Flow control around them Matt Faluotico

Transcript of Optionals by Matt Faluotico

var, let, & ?

Optionals & Flow control around themMatt Faluotico

Matt Faluotico

● Midwest born and raised, Ohio State● iOS Developer at Xero (accounting SaaS)● Employee App● 3 years of iOS

● Twitter: @mattfxyz● Web: mattf.xyz● Github: /mattfxyz

● Introductions● Objects● Var, Let, ● Optionals● Unwrapping● Implementing● Dependency injection● Conclusion● Q&A

Hello!

Objects

Objects in Swift

Everything is an object!

● Swift is still strongly typed, even if it doesn't quite look like it● Grew from C & Objective-C● Even primitives (Int, String, Bool, etc...)

Compiler will assume the type

var str = "Hello, With The Best" // Assumed to be a String

var specificStr: String = "Hello (again), With The Best"

Both are Strings!

● Reassignable to other Strings

print(str.dynamicType) // => String

print(specificStr.dynamicType) // => String

● Because we used var

Objects in Swift

var vs. let

Keyword for declaring a mutable object

● If you’re going to reassign the object● If you’re using structs

var str = "Hello, playground"

str = "A different playground"

● Compiler is okay with this

var

Keyword for declaring a constant object

● If you’re keep the same reference to an object● Your struct is not changing

let str = "Hello, playground"

str = "A different playground" // Compiler error

● Structs behave differently than classes

● Mutability is more defined by changing the pointer

let

let for classes

class MyStruct {

var number: Int

var name: String

}

let c = MyClass(number: 0, name: "cat")

s.number = 12 // This is not mutating the class

● Changing the properties on the heap

● Structs live on the stack○ Much faster

● But they have a constant size and are immutable● When you reassign to a struct, you create an entire new object on the stack

struct MyStruct {

var number: Int

var name: String

}

let s = MyStruct(number: 0, name: "cat")

//s.number = 12

● For structs this fails

let for structs

Remember our string?

var specificStr: String = "Hello (again), With The Best"

var specificStr: String = nil

● This breaks the things...

Objects can’t be nil

So we have Optionals

● A traditional type must hold a value (cannot be nil)● An optional wraps any type in a form that allows nil

“there is a value, and it equals x” – Swift Programming Language

● We use the ? to declare something as an optional

var str: String? = "Hello, With The Best"

Optionals

Why Optionals?

We know ahead of time if the object we're working with is capable of being nil and we can handle it appropriately.

● Why check to see if something is nil if it cannot be nil?● Let programmers consuming an API or library which parts are optional● Xcode's compiler leads to less mistakes● Objective-c compatibility: All pointers can be nil

We’ll always know if something could potentially be nil

● Force Unwrapping (!)○ Returns the value, but the program will crash if nil is found○ Using ! is called “unsafe” but still commonly used○ For unwrapping causes a runtime error when the object is nil

var str: String? = "Hello, With The Best"

print(str!)

● Optional Chaining (?)○ Returns the value IFF the value exists○ Will only execute if the object can be unwrapped

■ Will return nil if it can’t be unwrapped

var str: String? = "Hello, With The Best"

var n: = str?.characters.count

Unwrapping Optionals

● Should always unwrap optionals

let x = str?.characters.first

let a = str?.stringByAppendingString("cat")

let start = str?.startIndex

let end = str?.endIndex

● All of those question marks look messy● Everyone agrees

Unwrapping Optionals

● if-let is the solution

if let s = str {

let x = s.characters.first

let a = s.stringByAppendingString("cat")

let start = s.startIndex

let end = st.endIndex

}

● If we can unwrap the object, bind it to an immutable value● Since they’re objects, all the changes affect both

Optional Binding

Option Binding

if let s = aString,

let i = s.characters.count,

let b = aBool,

let f = aFloat {

print(s)

print(i)

print(b)

print(f)

print("everything was unwrapped!")

} else ...

● You can even check for multiple unwraps in one if-let statement● Use the previous unwrapped results in following conditions!● As soon as one value is nil, the condition is false

○ Handle that one with an else case!

Left Hand Flow

● Left should always be good● Ray Wenderlich says it best

“When coding with conditionals, the left hand margin of the code should be the "golden" or "happy" path. That is, don't nest if statements. Multiple return statements are OK”

● if-let puts the “happy” value on the left side, but it still requires nesting ifs

● Return early for readability

Left hand rule

Guard

● Check for a condition that must be true to continue in the scope● If it’s true, continue

○ But… you must leave inside the else block○ That new variable is also available for the rest of the scope

func makeRequest(sessionManager session: SessionManager?) {

guard sm = session else {

return

}

sm.something()

}

Implementation

Optionals are actually just Swift enums

enum Optional<T> : Reflectable, NilLiteralConvertible {

case None

case Some(T)

init()

init(_ some: T)

}

● Initialized with a value or with an object● The None case is just nil

Implementation

● Because they’re optionals, there are some cool thing we can do with them● A lower level version of if-let

○ Because if-let is just a shortcut

let someOptional: Int? = 42

if case Optional.Some(let x) = someOptional {

print(x)

}

if case let x? = someOptional {

print(x.dynamicType)

print(x)

}

Implementation

Only continue if the value can be unwrapped

for case let x? in a {

print(x)

}

You can check for conditions in loops

for var x in a where x > 34 {

print(x)

}

(this one still iterates over nil)

Same for for loops

Implicitly Unwrapped Optionals& “Dependency Injection”

Master → Details(most applications)

So you have a class...

class DetailViewController: UIViewController {

var username: String

var profilePicture: UIImage

...

}

● “Class __ has no initializers”● All non-optionals must have values after initialization● View Controllers don’t always fill all of their properties in initialization

You know that the value isn’t going to be nil when you want to use it…

The “Master” Controller is going to provide it

But you get an error

Let’s add optionals!

class DetailViewController: UIViewController {

var username: String?

var profilePicture: UIImage?

...

}

Not you have to unwrap for every use…

Nah

Let’s add optionals!

Implicitly Unwrapped Optionals

class DetailViewController: UIViewController {

var username: String?

var profilePicture: UIImage!

...

}

● In between a traditional object and an optional● Most commonly used in multi-step-initialization● “Compiler Magic”

“An implicitly unwrapped optional is a normal optional behind the scenes, but can also be used like a non optional value”

● They’re dangers. Be careful out there

Implicitly Unwrapped Optionals

Summary

● Type safe Swift● “Nil safe” from optionals● Left is happy● There’s a way around it