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

Daniel Steinberg: The Open World of Swift 3

1fa9cb8c7997c8c4d3d251fb5e41f749?s=47 Realm
April 25, 2016

Daniel Steinberg: The Open World of Swift 3

1fa9cb8c7997c8c4d3d251fb5e41f749?s=128

Realm

April 25, 2016
Tweet

Transcript

  1. The Open World of Swift 3 AppBuilders 2016 Daniel H

    Steinberg @dimsumthinking
  2. Swift

  3. Open

  4. Open?

  5. Open!

  6. Future

  7. Future?

  8. Future!

  9. What can we see?

  10. 0025 - Scoped Access Levels

  11. public internal private

  12. public internal private

  13. public internal private

  14. public internal private

  15. public internal fileprivate

  16. public internal fileprivate private

  17. class MyClass { private var myProperty = "Hello" private func

    myPrivateMethod() { print(myProperty) } fileprivate func myFilePrivateMethod(numberOfTimes times: Int) { for _ in 1 ... times { myPrivateMethod() } } } extension MyClass { func myExtensionMethod(numberOfTimes times: Int) { myInternalMethod(numberOfTimes: times) } }
  18. class MyClass { private var myProperty = "Hello" private func

    myPrivateMethod() { print(myProperty) } fileprivate func myFilePrivateMethod(numberOfTimes times: Int) { for _ in 1 ... times { myPrivateMethod() } } } extension MyClass { func myExtensionMethod(numberOfTimes times: Int) { myInternalMethod(numberOfTimes: times) } }
  19. class MyClass { private var myProperty = "Hello" private func

    myPrivateMethod() { print(myProperty) } fileprivate func myFilePrivateMethod(numberOfTimes times: Int) { for _ in 1 ... times { myPrivateMethod() } } } extension MyClass { func myExtensionMethod(numberOfTimes times: Int) { myInternalMethod(numberOfTimes: times) } }
  20. class MyClass { private var myProperty = "Hello" private func

    myPrivateMethod() { print(myProperty) } fileprivate func myFilePrivateMethod(numberOfTimes times: Int) { for _ in 1 ... times { myPrivateMethod() } } } extension MyClass { func myExtensionMethod(numberOfTimes times: Int) { myInternalMethod(numberOfTimes: times) } }
  21. class MyClass { private var myProperty = "Hello" private func

    myPrivateMethod() { print(myProperty) } fileprivate func myFilePrivateMethod(numberOfTimes times: Int) { for _ in 1 ... times { myPrivateMethod() } } } extension MyClass { func myExtensionMethod(numberOfTimes times: Int) { myInternalMethod(numberOfTimes: times) } }
  22. public internal fileprivate private

  23. 0004 - Remove ++ and —

  24. while count < upperLimit { print( myArray[count++]) }

  25. while count < upperLimit { print( myArray[count++]) }

  26. while count < upperLimit { print( myArray[count]) count += 1

    }
  27. 0007 - Remove C Style for loops with conditions and

    incrementors
  28. for (int i = 0; i < array.count; i++)

  29. for (int i = 0; i < array.count; i++)

  30. 0053 - Remove explicit use of let from Function Parameters

  31. func double(input: Int) -> Int { // ... }

  32. func double(let input: Int) -> Int { // ... }

  33. func double(let input: Int) -> Int { // ... }

  34. 0003 - Remove var from Function Parameters

  35. func double(input: Int) -> Int { input = input *

    2 return input }
  36. func double(var input: Int) -> Int { input = input

    * 2 return input }
  37. func double(var input: Int) -> Int { input = input

    * 2 return input }
  38. func double(input: Int) -> Int { var localInput = input

    localInput = localInput * 2 return localInput }
  39. func double(input: Int) -> Int { var localInput = input

    localInput = localInput * 2 return localInput }
  40. func double(input: Int) -> Int { var input = input

    input = input * 2 return input } Name Shadowing
  41. func double(input: Int) -> Int { var input = input

    input = input * 2 return input }
  42. 0031 - Adjusting inout Declarations for Type Decoration

  43. func double(input: Int) { input = input * 2 }

  44. func double(inout input: Int) { input = input * 2

    }
  45. func double(inout input: Int) { input = input * 2

    }
  46. func double(input: inout Int) { input = input * 2

    }
  47. 0053 - Limiting inout capture to @noescape context

  48. func escape(f: () -> ()) {} func example(inout x: Int)

    { escape { _ = x } }
  49. func escape(f: () -> ()) {} func example(inout x: Int)

    { escape { _ = x } }
  50. func escape(f: () -> ()) {} func example(inout x: Int)

    { escape { _ = x } }
  51. func escape(f: () -> ()) {} func example(inout x: Int)

    { escape { _ = x } }
  52. func escape(f: () -> ()) {} func example(inout x: Int)

    { escape { _ = x } }
  53. func escape(f: () -> ()) {} func example(inout x: Int)

    { escape { _ = x } }
  54. func escape(f: () -> ()) {} func example(inout x: Int)

    { escape { _ = x } }
  55. func noEscape(@noescape f: () -> ()) {} func example(inout x:

    Int) { noEscape { _ = x } }
  56. func noEscape(@noescape f: () -> ()) {} func example(inout x:

    Int) { noEscape { _ = x } } safe because @noescape => closure can't be called after function returns
  57. func escape(f: () -> ()) {} func example(inout x: Int)

    { escape { _ = x } }
  58. func escape(f: () -> ()) {} func example(inout x: Int)

    { escape {[x] in _ = x } }
  59. func escape(f: () -> ()) {} func example(inout x: Int)

    { escape {[x] in _ = x } } [x] is a capture list a constant is initialized to have the value of x
  60. 0049 - Move @noescape and @autoclosure to be type attributes

  61. func noEscape(@noescape f: () -> ()) {}

  62. func noEscape(f: @noescape () -> ()) {}

  63. func noEscape(f: @autoclosure () -> ()) {}

  64. 0002 - Remove currying func declaration syntax

  65. 0002 - Remove currying func declaration syntax

  66. 0002 - Remove currying func declaration syntax

  67. func curried(x: Int)(y: Int) -> Int { return {(y: Int)

    -> Int in return x * y } } curried(7)(8)
  68. func curried(x: Int)(y: Int) -> Int { return {(y: Int)

    -> Int in return x * y } } curried(7)(8)
  69. func curried(x: Int)(y: Int) -> Int { return {(y: Int)

    -> Int in return x * y } } curried(7)(8)
  70. func curried(x: Int)(y: Int) -> Int { return {(y: Int)

    -> Int in return x * y } } curried(7)(8)
  71. func curried(x: Int)(y: Int) -> Int { return {(y: Int)

    -> Int in return x * y } } curried(7)(8) 7 * y
  72. func curried(x: Int)(y: Int) -> Int { return {(y: Int)

    -> Int in return x * y } } curried(7)(8) 7 * 8
  73. func curried(x: Int)(y: Int) -> Int { return {(y: Int)

    -> Int in return x * y } } curried(7)(8)
  74. func curried(x: Int)(y: Int) -> Int { return {(y: Int)

    -> Int in return x * y } } curried(7)(8)
  75. func curried(x: Int)(y: Int) -> Int { return {(y: Int)

    -> Int in return x * y } } curried(7)(8)
  76. func curried(x: Int) -> (y: Int) -> Int { return

    {(y: Int) -> Int in return x * y } } curried(7)(8)
  77. func curried(x: Int) -> (y: Int) -> Int { return

    {(y: Int) -> Int in return x * y } } curried(7)(8)
  78. func curried(x: Int) -> (y: Int) -> Int { return

    {(y: Int) -> Int in return x * y } } curried(7)(8)
  79. func curried(x: Int) -> (y: Int) -> Int { return

    {(y: Int) -> Int in return x * y } } curried(7)(8)
  80. func curried(x: Int) -> (y: Int) -> Int { return

    {(y: Int) -> Int in return x * y } } curried(7)(8)
  81. Testing

  82. Playgrounds

  83. Package Manager

  84. Objective-C

  85. 0022 - Referencing the Obj-C selector of a method

  86. class MyClass : NSObject { func callbackMethod(with notification: NSNotification){} func

    setNotification() { let center = NSNotificationCenter.defaultCenter() center .addObserver(self, selector: "callbackMethod", name: NSApplicationWillResignActiveNotification, object: NSApplication.sharedApplication()) } }
  87. class MyClass : NSObject { func callbackMethod(with notification: NSNotification){} func

    setNotification() { let center = NSNotificationCenter.defaultCenter() center .addObserver(self, selector: "callbackMethod", name: NSApplicationWillResignActiveNotification, object: NSApplication.sharedApplication()) } }
  88. class MyClass : NSObject { func callbackMethod(with notification: NSNotification){} func

    setNotification() { let center = NSNotificationCenter.defaultCenter() center .addObserver(self, selector: "callbackMethod", name: NSApplicationWillResignActiveNotification, object: NSApplication.sharedApplication()) } }
  89. class MyClass : NSObject { func callbackMethod(with notification: NSNotification){} func

    setNotification() { let center = NSNotificationCenter.defaultCenter() center .addObserver(self, selector: "callbackMethod", name: NSApplicationWillResignActiveNotification, object: NSApplication.sharedApplication()) } }
  90. class MyClass : NSObject { func callbackMethod(with notification: NSNotification){} func

    setNotification() { let center = NSNotificationCenter.defaultCenter() center .addObserver(self, selector: "callbackMethod", name: NSApplicationWillResignActiveNotification, object: NSApplication.sharedApplication()) } }
  91. class MyClass : NSObject { func callbackMethod(with notification: NSNotification){} func

    setNotification() { let center = NSNotificationCenter.defaultCenter() center .addObserver(self, selector: "callbackMethod", name: NSApplicationWillResignActiveNotification, object: NSApplication.sharedApplication()) } }
  92. class MyClass : NSObject { func callbackMethod(with notification: NSNotification){} func

    setNotification() { let center = NSNotificationCenter.defaultCenter() center .addObserver(self, selector: #selector(callbackMethod), name: NSApplicationWillResignActiveNotification, object: NSApplication.sharedApplication()) } }
  93. class MyClass : NSObject { func callbackMethod(with notification: NSNotification){} func

    setNotification() { let center = NSNotificationCenter.defaultCenter() center .addObserver(self, selector: #selector(MyClass.callbackMethod), name: NSApplicationWillResignActiveNotification, object: NSApplication.sharedApplication()) } }
  94. class MyClass : NSObject { func callbackMethod(){} func callbackMethod(with notification:

    NSNotification){} func setNotification() { let center = NSNotificationCenter.defaultCenter() center .addObserver(self, selector: #selector(MyClass.callbackMethod), name: NSApplicationWillResignActiveNotification, object: NSApplication.sharedApplication()) } }
  95. class MyClass : NSObject { func callbackMethod(){} func callbackMethod(with notification:

    NSNotification){} func setNotification() { let center = NSNotificationCenter.defaultCenter() center .addObserver(self, selector: #selector(MyClass.callbackMethod), name: NSApplicationWillResignActiveNotification, object: NSApplication.sharedApplication()) } }
  96. class MyClass : NSObject { func callbackMethod(){} func callbackMethod(with notification:

    NSNotification){} func setNotification() { let center = NSNotificationCenter.defaultCenter() center .addObserver(self, selector: #selector(MyClass.callbackMethod(with:)), name: NSApplicationWillResignActiveNotification, object: NSApplication.sharedApplication()) } }
  97. 0033 - Import Obj-C constants as Swift types

  98. HK_EXTERN NSString * const HKQuantityTypeIdentifierBodyMassIndex; HK_EXTERN NSString * const HKQuantityTypeIdentifierBodyFatPercentage;

    HK_EXTERN NSString * const HKQuantityTypeIdentifierHeight; HK_EXTERN NSString * const HKQuantityTypeIdentifierBodyMass; HK_EXTERN NSString * const HKQuantityTypeIdentifierLeanBodyMass;
  99. HK_EXTERN NSString * const HKQuantityTypeIdentifierBodyMassIndex; HK_EXTERN NSString * const HKQuantityTypeIdentifierBodyFatPercentage;

    HK_EXTERN NSString * const HKQuantityTypeIdentifierHeight; HK_EXTERN NSString * const HKQuantityTypeIdentifierBodyMass; HK_EXTERN NSString * const HKQuantityTypeIdentifierLeanBodyMass;
  100. enum HKQuantityTypeIdentifier : String { case BodyMassIndex case BodyFatPercentage case

    Height case BodyMass case LeanBodyMass }
  101. enum HKQuantityTypeIdentifier : String { case BodyMassIndex case BodyFatPercentage case

    Height case BodyMass case LeanBodyMass }
  102. HK_EXTERN NSString * const HKQuantityTypeIdentifierBodyMassIndex; HK_EXTERN NSString * const HKQuantityTypeIdentifierBodyFatPercentage;

    HK_EXTERN NSString * const HKQuantityTypeIdentifierHeight; HK_EXTERN NSString * const HKQuantityTypeIdentifierBodyMass; HK_EXTERN NSString * const HKQuantityTypeIdentifierLeanBodyMass;
  103. enum HKQuantityTypeIdentifier : String { case BodyMassIndex case BodyFatPercentage case

    Height case BodyMass case LeanBodyMass }
  104. enum HKQuantityTypeIdentifier : String { case BodyMassIndex case BodyFatPercentage case

    Height case BodyMass case LeanBodyMass }
  105. 0005 - Better translation of Obj-C APIs into Swift

  106. let color = NSColor.blueColor()

  107. let color = NSColor.blueColor()

  108. let color = NSColor.blueColor() Prune redundant type names

  109. let color = NSColor.blue()

  110. rootViewController .presentViewController(alert, animated: true, completion: nil)

  111. rootViewController .presentViewController(alert, animated: true, completion: nil) Add default arguments

  112. rootViewController .presentViewController(alert, animated: true, completion: nil) Nullable trailing closures default

    = nil
  113. rootViewController .presentViewController(alert, animated: true)

  114. rootViewController .presentViewController(alert, animated: true) Shouldn't animated default = true

  115. rootViewController.presentViewController(alert)

  116. rootViewController.presentViewController(alert) Prune redundant type names

  117. rootViewController.present(alert)

  118. var empty: Bool

  119. var empty: Bool Prepend "is" to Bools

  120. var isEmpty: Bool

  121. addLineToPoint(myPoint)

  122. addLineToPoint(myPoint) func addLineToPoint(_: CGPoint)

  123. addLineToPoint(myPoint) func addLineToPoint(_: CGPoint) Add first argument labels

  124. addLineToPoint(myPoint) func addLineToPoint(_: CGPoint) Add first argument labels

  125. addLine(to: myPoint) func addLine(to point: CGPoint) Add first argument labels

  126. addLine(to: myPoint) func addLine(to point: CGPoint) Add first argument labels

  127. Add first argument labels

  128. Add first argument labels

  129. var URLHandler

  130. var URLHandler Lower case imported types

  131. var urlHandler Lower case imported types

  132. enum Currency { case Dollars case Euros case Pounds case

    Yen } Lower case imported types
  133. enum Currency { case Dollars case Euros case Pounds case

    Yen } Lower case imported types
  134. enum Currency { case dollars case euros case pounds case

    yen } Lower case imported types
  135. 0036 - Requiring Leading Dot Prefixes for Enum Instance Member

    Implementations
  136. enum Currency { case dollars case euros case pounds case

    yen var symbol: String { switch self { case dollars: return "$" default: return "I don't know" } } }
  137. enum Currency { case dollars case euros case pounds case

    yen var symbol: String { switch self { case .dollars: return "$" default: return "I don't know" } } }
  138. enum Currency { case dollars case euros case pounds case

    yen var symbol: String { switch self { case dollars: return "$" default: return "I don't know" } } }
  139. enum Currency { case dollars case euros case pounds case

    yen var symbol: String { switch self { case .dollars: return "$" default: return "I don't know" } } }
  140. enum Currency { case dollars case euros case pounds case

    yen var symbol: String { switch self { case .dollars: return "$" default: return "I don't know" } } }
  141. 0043 - Declare variables in 'case' labels with multiple patterns

  142. enum MyEnum { case case1(Int,Float) case case2(Float,Int) } switch value

    { case let .case1(x, 2), let .case2(2, x): print(x) case .case1, .case2: break }
  143. enum MyEnum { case case1(Int,Float) case case2(Float,Int) } switch value

    { case let .case1(x, 2), let .case2(2, x): print(x) case .case1, .case2: break }
  144. enum MyEnum { case case1(Int,Float) case case2(Float,Int) } switch value

    { case let .case1(x, 2), let .case2(2, x): print(x) case .case1, .case2: break }
  145. enum MyEnum { case case1(Int,Float) case case2(Float,Int) } switch value

    { case let .case1(x, 2), let .case2(2, x): print(x) case .case1, .case2: break }
  146. enum MyEnum { case case1(Int,Float) case case2(Float,Int) } switch value

    { case let .case1(x, 2), let .case2(2, x): print(x) case .case1, .case2: break }
  147. enum MyEnum { case case1(Int,Float) case case2(Float,Int) } switch value

    { case let .case1(x, 2), let .case2(2, x): print(x) case .case1, .case2: break }
  148. enum MyEnum { case case1(Int,Float) case case2(Float,Int) } switch value

    { case let .case1(x, 2), let .case2(2, x): print(x) case .case1, .case2: break }
  149. 0001 - Allow (most) keywords as argument labels

  150. calculateRevenue(for sales: Int, in currency: Currency)

  151. calculateRevenue(for sales: Int, in currency: Currency)

  152. calculateRevenue(for numberOfCopies, in .dollars)

  153. 0009 - Require self for accessing instance members

  154. struct Friend { let name: String let location: String func

    nameBadge() { print("I'm", name, "from", location) } }
  155. struct Friend { let name: String let location: String func

    nameBadge() { print("I'm", name, "from", location) } }
  156. struct Friend { let name: String let location: String func

    nameBadge() { print("I'm", name, "from", location) } }
  157. struct Friend { let name: String let location: String func

    nameBadge() { print("I'm", self.name, "from", self.location) } }
  158. struct Friend { let name: String let location: String func

    nameBadge() { print("I'm", self.name, "from", self.location) } } Require self for accessing instance members REJECTED
  159. 0011 - Replace typealias keyword with associatedtype for associated type

    declarations
  160. 0011 - Replace typealias keyword with associatedtype for associated type

    declarations
  161. protocol Prot { typealias Container : SequenceType } extension Prot

    { typealias Element = Container.Generator.Element }
  162. protocol Prot { typealias Container : SequenceType } extension Prot

    { typealias Element = Container.Generator.Element }
  163. protocol Prot { associatedtype Container : SequenceType } extension Prot

    { typealias Element = Container.Generator.Element }
  164. 0046 Establish consistent label behavior across all parameters including first

    labels
  165. func increase(ourNumber: Int, delta: Int) -> Int { } increase(6,

    delta: 3)
  166. func increase(ourNumber: Int, delta: Int) -> Int { } increase(6,

    delta: 3)
  167. func increase(ourNumber: Int, delta: Int) -> Int { } increase(6,

    delta: 3)
  168. func increase(ourNumber: Int, delta: Int) -> Int { } increase(6,

    delta: 3)
  169. func increase(ourNumber: Int, delta: Int) -> Int { } increase(ourNumber:

    6, delta: 3)
  170. func increase(_ ourNumber: Int, delta: Int) -> Int { }

    increase(6, delta: 3)
  171. 0023 - Swift API Guidelines

  172. Swift API Design Guidelines

  173. myArray.sort()

  174. sort() sorted()

  175. sortInPlace() sort()

  176. sort() sorted()

  177. sort() sorted() Name functions and methods according to their side-effects

  178. x.distance(to: y) i.successor() Those without side-effects should read as noun

    phrases
  179. x.sort() x.append(y) Those with side-effects should read as imperative noun

    phrases
  180. sort() sorted()/sorting() Use the “ed/ing” rule to name the nonmutating

    counterpart of a mutating method
  181. Prefer methods to free functions

  182. Prefer methods to free functions Protocol Extensions in Swift 2

  183. Prefer methods to free functions Protocol Extensions in Swift 2

    Except …
  184. min(x, y, z) When there's no obvious self

  185. print(x) When the function is an unconstrained generic

  186. sin(x) When the function is part of the established domain

    notation
  187. Methods can share a base name

  188. Methods can share a base name Good when they do

    analogous things
  189. Methods can share a base name Not good (tableView!) when

    they don't
  190. Choose good parameter names

  191. func move(from startingIndex: Int, to endingIndex: Int) Choose good parameter

    names
  192. Take advantage of default values

  193. Take advantage of default values func hello(name: String = "World")

  194. Take advantage of default values init(name: String, hometown: String? =

    nil)
  195. Prefer to locate parameters with defaults at the end init(name:

    String, hometown: String? = nil)
  196. External Argument Labels func move(from startingIndex: Int, to endingIndex: Int)

  197. move(from: here to: there)

  198. Argument Labels Exceptions

  199. min(number1, number2) Omit labels when arguments can't be distinguished

  200. Double(someInt) Omit labels in full width inits

  201. Double(_ anInt: someInt) Omit labels in full width inits

  202. func move(from startingIndex: Int, to endingIndex: Int) When the preposition

    applies to the whole
  203. func moveTo(x: Int, y: Int) When the preposition applies to

    the whole
  204. x.removeBoxes(having Length: 12) When the preposition applies to the whole

  205. None
  206. The Open World of Swift 3 AppBuilders 2016 Daniel H

    Steinberg @dimsumthinking