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

0ebf471a3ae8df42a84f93a7efbbdbd0?s=128

Ash Furrow

April 27, 2015
Tweet

Transcript

  1. Ash Furrow, Artsy Lessons from Production Swift

  2. February, 2014

  3. Swift Let’s talk about

  4. 1. The Need for Swift 2. The Fast and the

    Faulty 3. Seek Out Bold New Worlds
  5. Need Swift The for

  6. Objective-C

  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
  8. —John Siracusa “While hardware performance increases over time, the human

    capacity to deal with complexity does not.”
  9. Stuck Objective-C Past is in the

  10. Beyond Hope Objective-C is

  11. Criteria 1. No C baggage 2. Memory Managed 3. Native

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

    unicode strings 4. Native collections 5. Be concise 6. Named Parameters
  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
  14. Fast Faulty The and the

  15. Problems In Beta • Xcode crashes • Compiler segfaults •

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

    changes to Swift • Still some remaining language limitations
  17. Problems Now • Language changes tied to Xcode versions •

    Runtime changes tied to Xcode versions • Changes in resource-loading in frameworks
  18. Community Tools • Most still in their infancy • CocoaPods,

    Jazzy, SBConstants… • The rest do not exist (or are still in beta) • Test coverage analyzer
  19. Community Libraries • Struggling to accomodate frequent Swift changes •

    Xcode updates make this difficult
  20. The Fast and the Faulty • Swift had a rough

    start • Was to be expected • Things are better now • Mostly • Growing pains
  21. Seek Out New Worlds Bold

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

  23. Examples

  24. Index Paths • Used to identify cells in a table

    view • Section, row • Lots of horrendous code • It’s so bad • Seriously bad
  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 ...
  26. Index Paths switch (indexPath.section, indexPath.row) { case (0, 0): case

    (0, 1): case (1, 0): case (1, 1): default: // nop }
  27. Still Terrible This is

  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 }
  29. Generics • Define functions, structs, others in the abstract •

    Create one instead of many • Arrays, dictionaries, and sets are all generics
  30. Generics struct Stack<T> { private var contents = Array<T>() 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 } }
  31. Generics var intStack = Stack<Int>() var stringStack = Stack<String>() var

    stackStack = Stack<Stack<AnyObject>>() intStack.push(1) intStack.pop() // Returns 1
  32. Lazy Loading • Create resource when it is first accessed

    • Avoids unnecessary work for CPU • Avoids unnecessary memory use
  33. Lazy Objective-C • No language-level support • Lots of repetition

    • Tedious work • Lots of repetition
  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
  35. Lazy Swift class MyClass { lazy var name = "Ash

    Furrow" }
  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"
  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"
  38. Extending Types • Objective-C has “categories” for extending existing classes

    • Swift has “extensions” instead • They work on all types
  39. Extending Types extension Int { func times(closure: () -> ())

    { for i in 0..<self { closure() } } } 4.times { // Do something 4 times }
  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
  41. Functional Awesomeness let people = ["Carter", "Sebastian", "Daniel"] people.map {

    "Hello, \($0)!" } func hello(name: String) -> String { return "Hello, \(name)!" } people.map(hello) or…
  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"))
  43. Functional Awesomeness func say(greeting: String)(name: String) -> String { return

    "(greeting), \(name)!" } people.map(say("Hello")) people.map(say("Merhaba"))
  44. SBConstants • Generate constants for Storyboard identifiers • Compile-time checked

    enum • Can be extended…
  45. SBConstants func performSegue(identifier: SegueIdentifier) { performSegueWithIdentifier(identifier.rawValue, sender: self) } ...

    func ==(lhs: UIStoryboardSegue, rhs: SegueIdentifier) -> Bool { return lhs.identifier == rhs.rawValue }
  46. SBConstants peformSegue(.RegisterCreditCard) ... func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { if

    segue == .RegisterCreditCard { ... } }
  47. SBConstants • Don’t use rawValue all over the place •

    Abstract it away • Get compile-time safety
  48. Familiar Problems New Ways to solve Let’s look for

  49. For Advice Ask other communities Let’s

  50. Resources • Natasha the Robot’s newsletter • iOSDevWeekly • iOS

    Goodies • GitHub Explore • leanpub.com/yourfirstswiftapp
  51. Eidolon

  52. 1. The Need for Swift 2. The Fast and the

    Faulty 3. Seek Out Bold New Worlds
  53. Better Mistakes Make Tomorrow