Slide 1

Slide 1 text

CONNECT.TECH – September 22, 2017 CONNECT . TECH Patrick Seda - @pxtrick Crossing the Chasm Swift of

Slide 2

Slide 2 text

Target Material

Slide 3

Slide 3 text

Target Material This “Beyond Beginner”

Slide 4

Slide 4 text

Access Control

Slide 5

Slide 5 text

Access Control public open internal fileprivate private

Slide 6

Slide 6 text

Access Control class C class D file 2 class A class B file 1 module “consumer” // Class with a member variable. open class A { private var value }

Slide 7

Slide 7 text

Access Control class C class D file 2 class A class B file 1 module “consumer” // Class with a member variable. open class A { fileprivate var value }

Slide 8

Slide 8 text

Access Control class C class D file 2 class A class B file 1 module “consumer” // Class with a member variable. open class A { internal var value }

Slide 9

Slide 9 text

Access Control class C class D file 2 class A class B file 1 module “consumer” // Class with a member variable. open class A { public var value // Accessible, no override }

Slide 10

Slide 10 text

Access Control class C class D file 2 class A class B file 1 module “consumer” // Class with a member variable. open class A { open var value // Accessible, can override }

Slide 11

Slide 11 text

Most restrictive Access Control open public internal fileprivate private Least restrictive Default!

Slide 12

Slide 12 text

Access Control Why is the default level internal? “When you write a simple single-target app, the code in your app is typically self-contained within the app and doesn’t need to be made available outside of the app’s module. The default access level of internal already matches this requirement. Therefore, you don’t need to specify a custom access level.” Because: Less typing!

Slide 13

Slide 13 text

Most restrictive Access Control open public internal fileprivate private Least restrictive What should we do?

Slide 14

Slide 14 text

Named Model Types

Slide 15

Slide 15 text

Named Model Types enum vs. struct vs. class

Slide 16

Slide 16 text

Named Model Types // Modeling a Finite-State Machine. // State of the system. enum AlarmState { case disarmed case armed case alarming } // System-wide events. enum Event { case arm case disarm case tripSensor }

Slide 17

Slide 17 text

Named Model Types var currentState: AlarmState func handleEvent(_ event: Event) { switch event { case .arm: if (currentState == .disarmed) { currentState = .armed } case .disarm: currentState = .disarmed case .tripSensor: if (currentState == .armed) { currentState = .alarming } } }

Slide 18

Slide 18 text

Named Model Types var currentState: AlarmState = .disarmed handleEvent(.arm) // currentState == .armed handleEvent(.tripSensor) // currentState == .alarming handleEvent(.disarm) // currentState == .disarmed handleEvent(.tripSensor) // currentState == .disarmed

Slide 19

Slide 19 text

Named Model Types // Define some Gibson guitar types enum Gibson: String { case lesPaul case es355 case flyingV case sg } let myGuitar = Gibson.lesPaul print("My guitar is a \(myGuitar.rawValue)") let yourGuitar: Gibson = .flyingV print("Your guitar is a \(yourGuitar.rawValue)") Output: My guitar is a lesPaul Your guitar is a flyingV

Slide 20

Slide 20 text

Named Model Types // Define some Gibson guitar types enum Gibson: String { case lesPaul = "Les Paul" case es355 = "ES355" case flyingV = "Flying V" case sg = "SG" } let myGuitar = Gibson.lesPaul print("My guitar is a \(myGuitar.rawValue)") let yourGuitar: Gibson = .flyingV print("Your guitar is a \(yourGuitar.rawValue)") Output: My guitar is a Les Paul Your guitar is a Flying V

Slide 21

Slide 21 text

Named Model Types struct & class

Slide 22

Slide 22 text

Named Model Types When should we use struct vs. class? “In all other cases, define a class, and create instances of that class to be managed and passed by reference. In practice, this means that most custom data constructs should be classes, not structures.” Use a struct when: - Encapsulate few, simple data values - Data can be copied (passed by value) - Does not need inheritance

Slide 23

Slide 23 text

Protocols for Design

Slide 24

Slide 24 text

Protocols for Design A game

Slide 25

Slide 25 text

Protocols for Design

Slide 26

Slide 26 text

Protocols for Design Design before coding!

Slide 27

Slide 27 text

Musician Protocols for Design Musical Instrument Stringed Instrument Cello Viola Violin Bass makeSound() numStrings perform()

Slide 28

Slide 28 text

Protocols for Design protocol MusicalInstrument { func makeSound() } protocol StringedInstrument: MusicalInstrument { var numStrings: Int { get } } extension StringedInstrument { func makeSound() { print("Plink") } } class Cello: StringedInstrument { var numStrings: Int = 4 func makeSound() { print(”Hurrm Hummm") } } class Bass: StringedInstrument { var numStrings: Int = 4 func makeSound() { print("A Boom Boom Boom") } }

Slide 29

Slide 29 text

Protocols for Design class Musician { var instrument: MusicalInstrument? func perform() { instrument?.makeSound() } } let cello: MusicalInstrument = Cello() let bass: MusicalInstrument = Bass() let musician = Musician() musician.instrument = cello musician.perform() musician.instrument = bass musician.perform() Output: Hurrm Hummm A Boom Boom Boom

Slide 30

Slide 30 text

Closures

Slide 31

Slide 31 text

Closures callbacks

Slide 32

Slide 32 text

Closures // Do some stuff and fire a callback. func increment(_ value: inout Int, onDone onDone: () -> Void) { value += 1 onDone() } // Define our callback. var doneCb = { print("Done! value = \(value)") } // Test it out. var value = 3; increment(&value, onDone: doneCb) increment(&value, onDone: doneCb) Done! value = 4 Done! value = 5 Output:

Slide 33

Slide 33 text

Closures Unknown time of execution

Slide 34

Slide 34 text

Closures var queue = DispatchQueue.global() // Run using a thread pool. func execute(_ work: () -> Void) { queue.sync { work() } } // Create some work. var workItemOne = { print("Work item 1") } var workItemTwo = { print("Work item 2") } execute(workItemOne) execute(workItemTwo) Work item 1 Work item 2 Output:

Slide 35

Slide 35 text

Closures var queue = DispatchQueue.global() // Run using a thread pool. func execute(_ work: () -> Void) { queue.async { work() } } // Create some work. var workItemOne = { print("Work item 1") } var workItemTwo = { print("Work item 2") } execute(workItemOne) execute(workItemTwo) error: closure use of non-escaping parameter 'work' may allow it to escape Output:

Slide 36

Slide 36 text

Closures var queue = DispatchQueue.global() // Run using a thread pool. func execute(_ work: @escaping () -> Void) { queue.async { work() } } // Create some work. var workItemOne = { print("Work item 1") } var workItemTwo = { print("Work item 2") } execute(workItemOne) execute(workItemTwo) Work item 1 Work item 2 Output:

Slide 37

Slide 37 text

Closures Unknown time of execution … denuo

Slide 38

Slide 38 text

Closures // Work to be executed in the future. var futures: [() -> Void] = [] func queue(future work: () -> Void) { futures.append(work) } // Queue up some closures. queue(future: { print("Hey!") }) queue(future: { print("What?") }) // Execute each closure. for future in futures { future() } error: passing non-escaping parameter 'future' to function expecting an @escaping closure Output:

Slide 39

Slide 39 text

Closures // Work to be executed in the future. var futures: [() -> Void] = [] func queue(future work: @escaping () -> Void) { futures.append(work) } // Queue up some closures. queue(future: { print("Hey!") }) queue(future: { print("What?") }) // Execute each closure. for future in futures { future() } Hey! What? Output:

Slide 40

Slide 40 text

Memory Leaks

Slide 41

Slide 41 text

Memory Leaks ARC - Automatic Reference Counting

Slide 42

Slide 42 text

Memory Leaks // A noble warrior. class Knight { var horse: Horse? deinit { print("[Knight] - deinit()") } } // A valiant steed. class Horse { var knight: Knight? deinit { print("[Horse] - deinit()") } }

Slide 43

Slide 43 text

Memory Leaks // Create our knight. var hero: Knight? = Knight() // Create our horse. var stallion: Horse? = Horse() // Establish a beautiful friendship. hero?.horse = stallion stallion?.knight = hero // Clean up. print("Removing hero ...") hero = nil print("Removing stallion ...") stallion = nil Removing hero ... Removing stallion ... Output:

Slide 44

Slide 44 text

Memory Leaks var hero strong strong strong var stallion strong horse: hero knight: stallion

Slide 45

Slide 45 text

Memory Leaks var hero horse: hero strong strong var stallion knight: stallion

Slide 46

Slide 46 text

Memory Leaks // A noble warrior. class Knight { var horse: Horse? deinit { print("[Knight] - deinit()") } } // A valiant steed. class Horse { var knight: Knight? deinit { print("[Horse] - deinit()") } }

Slide 47

Slide 47 text

Memory Leaks // A noble warrior. class Knight { var horse: Horse? deinit { print("[Knight] - deinit()") } } // A valiant steed. class Horse { weak var knight: Knight? deinit { print("[Horse] - deinit()") } }

Slide 48

Slide 48 text

Memory Leaks var hero strong strong var stallion strong weak knight: stallion horse: hero

Slide 49

Slide 49 text

Memory Leaks var hero var stallion knight: stallion horse: hero

Slide 50

Slide 50 text

Memory Leaks // Create our knight. var hero: Knight? = Knight() // Create our horse. var stallion: Horse? = Horse() // Establish a beautiful friendship. hero?.horse = stallion stallion?.knight = hero // Clean up. print("Removing hero ...") hero = nil print("Removing stallion ...") stallion = nil Removing hero ... [Knight] - deinit() Removing stallion ... [Horse] - deinit() Output:

Slide 51

Slide 51 text

Memory Leaks // A noble warrior. class Knight { var esquire: Esquire? deinit { print("[Knight] - deinit()") } } // A knight’s assistant. class Esquire { var knight: Knight init(_ knight: Knight) { self.knight = knight } deinit { print("[Esquire] - deinit()") } }

Slide 52

Slide 52 text

Memory Leaks // Create our knight. var hero: Knight? = Knight() // Create and assign our assistant. hero?.esquire = Esquire(hero!) // Clean up. print("Removing hero ...") hero = nil Removing hero ... Output:

Slide 53

Slide 53 text

Memory Leaks var hero esquire: hero knight: esquire strong strong strong

Slide 54

Slide 54 text

Memory Leaks var hero strong strong esquire: hero knight: esquire

Slide 55

Slide 55 text

Memory Leaks // A noble warrior. class Knight { var esquire: Esquire? deinit { print("[Knight] - deinit()") } } // A knight’s assistant. class Esquire { unowned var knight: Knight init(_ knight: Knight) { self.knight = knight } deinit { print("[Esquire] - deinit()") } }

Slide 56

Slide 56 text

Memory Leaks var hero strong strong unowned esquire: hero knight: esquire

Slide 57

Slide 57 text

Memory Leaks var hero esquire: hero knight: esquire

Slide 58

Slide 58 text

Memory Leaks // Create our knight. var hero: Knight? = Knight() // Create and assign our assistant. hero?.esquire = Esquire(hero!) // Clean up. print("Removing hero ...") hero = nil Removing hero ... [Knight] - deinit() [Esquire] - deinit() Output:

Slide 59

Slide 59 text

CONNECT . TECH Patrick Seda - @pxtrick Thank You!