$30 off During Our Annual Pro Sale. View Details »

Lessons from Production Swift

Lessons from Production Swift

This is a presentation I gave at Istanbul Tech Talks about my work writing Swift in production. It discusses why we need Swift, some problems I've faced using it, and how it enables new problem-solving techniques.

http://www.istanbultechtalks.com

Ash Furrow

April 27, 2015
Tweet

More Decks by Ash Furrow

Other Decks in Programming

Transcript

  1. Ash Furrow, Artsy
    Lessons
    from
    Production Swift

    View Slide

  2. February, 2014

    View Slide

  3. Swift
    Let’s talk about

    View Slide

  4. 1. The Need for Swift
    2. The Fast and the Faulty
    3. Seek Out Bold New Worlds

    View Slide

  5. Need
    Swift
    The
    for

    View Slide

  6. Objective-C

    View Slide

  7. TXS ;push return address back onto stack
    LDY #$00 ;load Y with zero - will hold result
    LOOP1 LDAA TEMP ;load A into TEMP
    ANDA MASK ;AND A with Mask
    BNE ADD1
    BRA NONE1
    ADD1 INY ;increment our counter of 1's
    NONE1 LDAA TEMP ;reload accumulator A
    LSL MASK ;Shift the mask's 1 bit left
    BNE LOOP1 ;If we haven't finished our loop, branch
    LDAA #$01 ;load new mask into A
    STAA MASK ;store the reset mask into MASK
    TSX ;pull of return address and store in X
    PULA ;pull off A
    STAA TEMP ;store the value into temp
    TXS ;push return address back onto the stack
    LOOP2 LDAA TEMP ;Load A into TEMP
    ANDA MASK ;logical AND MASK with A
    BNE ADD2 ;add one if we need to
    BRA NONE2
    ADD2 INY ;increment our counter of 1's
    NONE2 LDAA TEMP
    LSL MASK ;shift our mask left by one
    BNE LOOP2 ;loop back until we've exhausted positions
    STY TEMP ;store Y into TEMP - this is the number of 1's
    LDAB TEMP ;load the number of 1's into B
    LDAA #$10 ;load dec 16 into A
    SBA ;A - B -> A same as 16 - B -> A

    View Slide

  8. —John Siracusa
    “While hardware performance increases over time,
    the human capacity to deal with complexity does not.”

    View Slide

  9. Stuck
    Objective-C
    Past
    is
    in the

    View Slide

  10. Beyond Hope
    Objective-C
    is

    View Slide

  11. Criteria
    1. No C baggage
    2. Memory Managed
    3. Native unicode strings
    4. Native collections
    5. Be concise
    6. Named Parameters

    View Slide

  12. Criteria
    1. No C baggage
    2. Memory Managed
    3. Native unicode strings
    4. Native collections
    5. Be concise
    6. Named Parameters






    View Slide

  13. The Need for Swift
    • Programming abstraction increases over time
    • Objective-C has improved all it can
    • Swift is the next step
    • Revolution, not evolution

    View Slide

  14. Fast
    Faulty
    The
    and the

    View Slide

  15. Problems In Beta
    • Xcode crashes
    • Compiler segfaults
    • Constant changes to Swift
    • Many language limitations

    View Slide

  16. Problems Now
    • Still some stability issues
    • Still frequent changes to Swift
    • Still some remaining language limitations

    View Slide

  17. Problems Now
    • Language changes tied to Xcode versions
    • Runtime changes tied to Xcode versions
    • Changes in resource-loading in frameworks

    View Slide

  18. Community Tools
    • Most still in their infancy
    • CocoaPods, Jazzy, SBConstants…
    • The rest do not exist (or are still in beta)
    • Test coverage analyzer

    View Slide

  19. Community Libraries
    • Struggling to accomodate frequent Swift changes
    • Xcode updates make this difficult

    View Slide

  20. The Fast and the Faulty
    • Swift had a rough start
    • Was to be expected
    • Things are better now
    • Mostly
    • Growing pains

    View Slide

  21. Seek Out
    New Worlds
    Bold

    View Slide

  22. Problem Solving in Objective-C
    Problem Solving in Swift
    is not

    View Slide

  23. Examples

    View Slide

  24. Index Paths
    • Used to identify cells in a table view
    • Section, row
    • Lots of horrendous code
    • It’s so bad
    • Seriously bad

    View Slide

  25. Index Paths
    if (indexPath.section == 0) {
    if (indexPath.row == 0) {
    } else if (indexPath.row == 1) {

    } else if ...
    } else if (indexPath.section == 1) {
    if (indexPath.row == 0) {
    } else if (indexPath.row == 1) {

    } else if ...
    } else if ...

    View Slide

  26. Index Paths
    switch (indexPath.section, indexPath.row) {
    case (0, 0):
    case (0, 1):
    case (1, 0):
    case (1, 1):
    default:
    // nop
    }

    View Slide

  27. Still Terrible
    This is

    View Slide

  28. Index Paths
    switch (indexPath.section, indexPath.row) {
    case (0, let row):
    // Executed for any section 0, row is row
    case (let section, 0) where section % 2 == 1:
    // Executed for first rows of odd all sections
    case (let section, let row) where validate(section):
    // Executed when validate() returns true
    default:
    // Executed on all other cases
    }

    View Slide

  29. Generics
    • Define functions, structs, others in the abstract
    • Create one instead of many
    • Arrays, dictionaries, and sets are all generics

    View Slide

  30. Generics
    struct Stack {
    private var contents = Array()
    mutating func push(value: T) {
    contents.insert(value, atIndex: 0)
    }
    mutating func pop() -> T {
    return contents.removeAtIndex(0)
    }
    var isEmpty: Bool {
    return countElements(contents) == 0
    }
    }

    View Slide

  31. Generics
    var intStack = Stack()
    var stringStack = Stack()
    var stackStack = Stack>()
    intStack.push(1)
    intStack.pop() // Returns 1

    View Slide

  32. Lazy Loading
    • Create resource when it is first accessed
    • Avoids unnecessary work for CPU
    • Avoids unnecessary memory use

    View Slide

  33. Lazy Objective-C
    • No language-level support
    • Lots of repetition
    • Tedious work
    • Lots of repetition

    View Slide

  34. Lazy Objective-C
    @interface MyClass: NSObject
    @property (nonatomic, copy) NSString *name;
    @end
    @implementation
    - (NSString *)name {
    if (_name == nil) {
    _name = "Ash Furrow";
    }
    return _name;
    }
    @end

    View Slide

  35. Lazy Swift
    class MyClass {
    lazy var name = "Ash Furrow"
    }

    View Slide

  36. Lazy Swift
    class MyClass {
    lazy var name = "Ash Furrow"
    }
    MyClass().name // Returns "Ash Furrow"
    let instance = MyClass()
    instance.name = "Orta Therox"
    instance.name // Returns “Orta Therox"

    View Slide

  37. Lazy Swift
    class MyClass {
    lazy var name = "Ash Furrow”
    lazy var greeting: String = {
    return "Hello, \(self.name)"
    }()
    }
    MyClass().greeting // Returns "Hello, Ash Furrow"
    let instance = MyClass()
    instance.name = "Orta Therox"
    instance.greeting // Returns "Hello, Orta Therox"
    instance.name = "Eloy Durán"
    instance.greeting // Returns "Hello, Orta Therox"

    View Slide

  38. Extending Types
    • Objective-C has “categories” for extending
    existing classes
    • Swift has “extensions” instead
    • They work on all types

    View Slide

  39. Extending Types
    extension Int {
    func times(closure: () -> ()) {
    for i in 0..closure()
    }
    }
    }
    4.times {
    // Do something 4 times
    }

    View Slide

  40. Extending Types
    extension Int {
    var hours: NSTimeInterval {
    return NSTimeInterval(3600 * self)
    }
    }
    extension NSTimeInterval {
    var fromNow: NSDate {
    return NSDate(timeIntervalSinceNow: self)
    }
    var ago: NSDate {
    NSDate(timeIntervalSinceNow: -self)
    }
    }
    4.hours.fromNow
    4.hours.ago

    View Slide

  41. Functional Awesomeness
    let people = ["Carter", "Sebastian", "Daniel"]
    people.map { "Hello, \($0)!" }
    func hello(name: String) -> String {
    return "Hello, \(name)!"
    }
    people.map(hello)
    or…

    View Slide

  42. Functional Awesomeness
    func say(greeting: String) -> (name: String) -> String {
    return { (name: String) -> String in
    "(greeting), \(name)!"
    }
    }
    people.map(say("Hello"))
    people.map(say("Merhaba"))

    View Slide

  43. Functional Awesomeness
    func say(greeting: String)(name: String) -> String {
    return "(greeting), \(name)!"
    }
    people.map(say("Hello"))
    people.map(say("Merhaba"))

    View Slide

  44. SBConstants
    • Generate constants for Storyboard identifiers
    • Compile-time checked enum
    • Can be extended…

    View Slide

  45. SBConstants
    func performSegue(identifier: SegueIdentifier) {
    performSegueWithIdentifier(identifier.rawValue, sender: self)
    }
    ...
    func ==(lhs: UIStoryboardSegue, rhs: SegueIdentifier) -> Bool {
    return lhs.identifier == rhs.rawValue
    }

    View Slide

  46. SBConstants
    peformSegue(.RegisterCreditCard)
    ...
    func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue == .RegisterCreditCard {
    ...
    }
    }

    View Slide

  47. SBConstants
    • Don’t use rawValue all over the place
    • Abstract it away
    • Get compile-time safety

    View Slide

  48. Familiar Problems
    New Ways
    to solve
    Let’s look for

    View Slide

  49. For Advice
    Ask
    other communities
    Let’s

    View Slide

  50. Resources
    • Natasha the Robot’s newsletter
    • iOSDevWeekly
    • iOS Goodies
    • GitHub Explore
    • leanpub.com/yourfirstswiftapp

    View Slide

  51. Eidolon

    View Slide

  52. 1. The Need for Swift
    2. The Fast and the Faulty
    3. Seek Out Bold New Worlds

    View Slide

  53. Better Mistakes
    Make
    Tomorrow

    View Slide