Optionals by Matt Faluotico
-
Upload
withthebest -
Category
Technology
-
view
209 -
download
0
Transcript of Optionals by Matt 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 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
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
● 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 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()
}
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
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?
...
}
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