Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Swift - Beyond Beginner

Patrick Seda
February 22, 2018

Swift - Beyond Beginner

Patrick Seda

February 22, 2018
Tweet

More Decks by Patrick Seda

Other Decks in Programming

Transcript

  1. Background @pxtrick “The Effects of RR-Interval Data on Heart Rate

    Variability and Congestive Heart Failure” Then: Now: Mobile and Web Business Apps Atlanta-ish, GA @pxtrick Patrick Seda Increasing the Quality of the Universe
  2. file 2 class A class B file 1 module “consumer”

    Access Control @pxtrick class C
  3. file 2 class A class B file 1 module “consumer”

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

    // Class with a member variable. class A { fileprivate var value } Access Control @pxtrick class C
  5. class C file 2 class A class B file 1

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

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

    // Class with a member variable. class A { open var value // Accessible, can override } Access Control @pxtrick class C
  8. 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 for small apps! Access Control @pxtrick
  9. -open -public -internal -fileprivate -private What should we do? Access

    Control @pxtrick Most restrictive Least restrictive
  10. // 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 } Named Model Types @pxtrick
  11. 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 } } } Named Model Types @pxtrick
  12. var currentState: AlarmState = .disarmed handleEvent(.arm) // currentState == .armed

    handleEvent(.tripSensor) // currentState == .alarming handleEvent(.disarm) // currentState == .disarmed handleEvent(.tripSensor) // currentState == .disarmed Named Model Types @pxtrick
  13. // Define some Gibson guitar types enum Gibson: String {

    case lesPaul case es355 case flyingV case sg } Named Model Types @pxtrick
  14. // 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)") My guitar is a lesPaul Your guitar is a flyingV Named Model Types @pxtrick Ou t p u t :
  15. // 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)") My guitar is a Les Paul Your guitar is a Flying V Named Model Types @pxtrick Ou t p u t :
  16. 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 Named Model Types @pxtrick
  17. 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") } } Protocols for Design @pxtrick
  18. 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() Hurrm Hummm A Boom Boom Boom Protocols for Design @pxtrick Ou t p u t :
  19. // Do some stuff and then fire a callback. func

    doSomething( /* ??? */ ) { // ... onDone() } Closures - C a l lb a cks @pxtrick
  20. // Increment an integer and fire a callback. func increment(_

    value: inout Int, onDone onDone: () -> Void) { value += 1 onDone() } // Define our callback. var attentionCb = { print("Attention! value = \(value)") } // Test it out. var value = 3; increment(&value, onDone: attentionCb) increment(&value, onDone: attentionCb) Attention! value = 4 Attention! value = 5 @pxtrick Ou t p u t : Closures - C a l lb a cks
  21. 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 @pxtrick Ou t p u t : Closures - T i m e of E xecu t ion
  22. 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 @pxtrick Ou t p u t : Closures - T i m e of E xecu t ion
  23. 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 2 Work item 1 @pxtrick Ou t p u t : Closures - T i m e of E xecu t ion
  24. let cities = ["Geneva", "Traer", "Mint Hill", "Senoia"] // Define

    a normal comparison function. func backwards(_ s1: String, _ s2: String) { return s1 > s2 } // Execute the array sort. var reversedOrder = cities.sorted(by: backwards) print("\(reversedOrder)") ["Traer", "Senoia", "Mint Hill", "Geneva"] @pxtrick Ou t p u t : Closures - C l os u r e E xp r e s s io n s
  25. let cities = ["Geneva", "Traer", "Mint Hill", "Senoia"] // Closure

    Expression syntax. var reversedOrder = cities.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 }) ["Traer", "Senoia", "Mint Hill", "Geneva"] @pxtrick Ou t p u t : Closures - C l os u r e E xp r e s s io n s
  26. let cities = ["Geneva", "Traer", "Mint Hill", "Senoia"] // Inferring

    type from context. var reversedOrder = cities.sorted(by: { s1, s2 in return s1 > s2 }) ["Traer", "Senoia", "Mint Hill", "Geneva"] @pxtrick Ou t p u t : Closures - C l os u r e E xp r e s s io n s
  27. let cities = ["Geneva", "Traer", "Mint Hill", "Senoia"] // Implicit

    returns from single-expression closures. var reversedOrder = cities.sorted(by: { s1, s2 in s1 > s2 }) ["Traer", "Senoia", "Mint Hill", "Geneva"] @pxtrick Ou t p u t : Closures - C l os u r e E xp r e s s io n s
  28. let cities = ["Geneva", "Traer", "Mint Hill", "Senoia"] // Shorthand

    argument names. var reversedOrder = cities.sorted(by: { $0 > $1 }) ["Traer", "Senoia", "Mint Hill", "Geneva"] @pxtrick Ou t p u t : Closures - C l os u r e E xp r e s s io n s
  29. let cities = ["Geneva", "Traer", "Mint Hill", "Senoia"] // Operator

    methods. var reversedOrder = cities.sorted(by: >) ["Traer", "Senoia", "Mint Hill", "Geneva"] @pxtrick Ou t p u t : Closures - C l os u r e E xp r e s s io n s
  30. let cities = ["Geneva", "Traer", "Mint Hill", "Senoia"] // Operator

    methods. var reversedOrder = cities.sorted(by: >) ["Traer", "Senoia", "Mint Hill", "Geneva"] @pxtrick Ou t p u t : // Closure Expression syntax. var reversedOrder = cities.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 }) Previously: Closures - C l os u r e E xp r e s s io n s
  31. // A rockin’ band. class RockBand { var keys: Keyboard?

    deinit { print("[RockBand] - deinit()") } } // A tasty delight. class Keyboard { var band: RockBand? deinit { print("[Keyboard] - deinit()") } } Memory Leaks @pxtrick
  32. // Create our band. var band: RockBand? = RockBand() //

    Create our keys. var keys: Keyboard? = Keyboard() // Establish a beautiful friendship. band?.keys = keys keys?.band = band // Clean up. print("Removing band ...") band = nil print("Removing keys ...") keys = nil Removing band ... Removing keys ... Memory Leaks @pxtrick Ou t p u t :
  33. var band strong strong strong var keys strong <RockBand instance>

    keys: <Keyboard instance> band <Keyboard instance> band: <RockBand instance> keys Memory Leaks @pxtrick
  34. var band strong strong var keys strong <RockBand instance> keys:

    <Keyboard instance> band <Keyboard instance> band: <RockBand instance> keys Memory Leaks @pxtrick
  35. var band strong strong var keys <RockBand instance> keys: <Keyboard

    instance> band <Keyboard instance> band: <RockBand instance> keys Memory Leaks @pxtrick
  36. // A rockin’ band. class RockBand { var keys: Keyboard?

    deinit { print("[RockBand] - deinit()") } } // A tasty delight. class Keyboard { weak var band: RockBand? deinit { print("[Keyboard] - deinit()") } } Memory Leaks @pxtrick
  37. var band strong strong var keys strong <RockBand instance> keys:

    <Keyboard instance> band <Keyboard instance> band: <RockBand instance> keys Memory Leaks @pxtrick weak
  38. var band strong var keys strong <RockBand instance> keys: <Keyboard

    instance> band <Keyboard instance> band: <RockBand instance> keys Memory Leaks @pxtrick weak
  39. var band var keys strong <RockBand instance> keys: <Keyboard instance>

    band <Keyboard instance> band: <RockBand instance> keys Memory Leaks @pxtrick
  40. var band var keys <RockBand instance> keys: <Keyboard instance> band

    <Keyboard instance> band: <RockBand instance> keys Memory Leaks @pxtrick
  41. var band var keys <RockBand instance> keys: <Keyboard instance> band

    <Keyboard instance> band: <RockBand instance> keys Memory Leaks @pxtrick
  42. // Create our band. var band: RockBand? = RockBand() //

    Create our keys. var keys: Keyboard? = Keyboard() // Establish a beautiful friendship. band?.keys = keys keys?.band = band // Clean up. print("Removing band ...") band = nil print("Removing keys ...") keys = nil Removing band ... [RockBand] - deinit() Removing keys ... [Keyboard] - deinit() Memory Leaks @pxtrick Ou t p u t :
  43. // A rock show. class Concert { var fans: Audience?

    deinit { print("[Concert] - deinit()") } } // The fans. class Audience { var concert: Concert init(_ concert: Concert) { self.concert = concert } deinit { print("[Audience] - deinit()") } } Memory Leaks @pxtrick
  44. // Create our rock show. var rockShow: Concert? = Concert()

    // Create and assign our fans. rockShow?.fans = Audience(rockShow!) // Clean up. print("Removing rockShow...") rockShow = nil Removing rockShow ... Memory Leaks @pxtrick Ou t p u t :
  45. var rockShow <Concert instance> fans: <Audience instance> rockShow <Audience instance>

    concert: <Concert instance> audience strong strong strong Memory Leaks @pxtrick
  46. var rockShow strong strong <Concert instance> fans: <Audience instance> rockShow

    <Audience instance> concert: <Concert instance> audience Memory Leaks @pxtrick
  47. // A rock show. class Concert { var fans: Audience?

    deinit { print("[Concert] - deinit()") } } // The fans. class Audience { unowned var concert: Concert init(_ concert: Concert) { self.concert = concert } deinit { print("[Audience] - deinit()") } } Memory Leaks @pxtrick
  48. var rockShow <Concert instance> fans: <Audience instance> rockShow <Audience instance>

    concert: <Concert instance> audience strong strong Memory Leaks @pxtrick unowned
  49. var rockShow <Concert instance> fans: <Audience instance> rockShow <Audience instance>

    concert: <Concert instance> audience strong Memory Leaks @pxtrick unowned
  50. var rockShow <Concert instance> fans: <Audience instance> rockShow <Audience instance>

    concert: <Concert instance> audience Memory Leaks @pxtrick
  51. // Create our rock show. var rockShow: Concert? = Concert()

    // Create and assign our fans. rockShow?.fans = Audience(rockShow!) // Clean up. print("Removing rockShow...") rockShow = nil Removing rockShow ... [Concert] - deinit() [Audience] - deinit() Ou t p u t : Memory Leaks @pxtrick