Swift 3 - From Expert to Beginner

Swift 3 - From Expert to Beginner

A speech for changes in Swift 3.

318643095c83b914cf80a7f99f247fe6?s=128

Wei Wang

July 21, 2016
Tweet

Transcript

  1. SP TF JP20028 - onevcat Wei Wang 1

  2. Recently 2

  3. Swift From Beginner to Expert JP20028 - onevcat, Nov 2014

    3
  4. Swift 3 From Expert to Beginner JP20028 - onevcat, Jul

    2016 4
  5. Open + Evolution 5

  6. Swift Evolution Repo1 SE-XXXX New Site: https://apple.github.io/ swift-evolution/ 1 https://github.com/apple/swift-evolution

    6
  7. 7

  8. Important proposals & Broken APIs 8

  9. SE-0023 API Design Guidelines And SE-0006 Apply API Guidelines to

    the Standard Library SE-0005 Better Translation of Objective-C APIs Into Swift SE-0033 Import Objective-C Constants as Swift Types 9
  10. Problems of Current Cocoa APIs • Disordered • Verbose &

    Duplicated • For Objective-C. Not Swifty 10
  11. Clarity let text = "Hello world" text.stringByAppendingString(", Swift2") 11

  12. Clarity public func stringByAppendingString(aString: String) -> String 12

  13. Clarity public func stringByAppendingString(aString: String) -> String 13

  14. Clarity public func appending(_ aString: String) -> String 14

  15. Clarity // Swift 2 text.stringByAppendingString(", Swift2") // Swift 3 text.appending(",

    Swift3") 15
  16. More Examples // Swift 2 let color = UIColor.blackColor() let

    app = UIApplication.sharedApplication() // Swift 3 let color = UIColor.black() // view.backGroundColor = .black() <- Type Infer let app = UIApplication.shared 16
  17. More Examples var array = [1, 2, 3, 4] //Swift

    2 array.removeAtIndex(1) // Swift 3 array.remove(at: 1) 17
  18. More Examples let text = "abcde" // Swift 2 text.stringByReplacingOccurrencesOfString(

    "abc", withString: "123") // Swift 3 text.replacingOccurrences( of: "abc", with: "123") 18
  19. Exception // Remove KVO observer // Swift 2 app.removeObserver(self, forKeyPath:

    "valueKey") // Swift 3 app.removeObserver(self, forKeyPath: "valueKey") // Why not? app.remove(observer: self, for: "valueKey") 19
  20. Exception func removeObserver( _ observer: NSObject, forKeyPath keyPath: String )

    When NSObject, Any, AnyObject, Int, String included in method signature: • Declaration is fine. • But using is not so clear. 20
  21. From Swift 2 To 3 Get to be used to

    new APIs With Swift migrator Difficulty: ! 21
  22. SE-0088 Modernize libdispatch for Swift 3 naming conventions 22

  23. // Swift 2 let queue = dispatch_queue_create( "my.queue", DISPATCH_QUEUE_CONCURRENT) dispatch_async(queue)

    { doHeavyWork() dispatch_async(dispatch_get_main_queue(), { updateUI() }) } dispatch_after( dispatch_time( DISPATCH_TIME_NOW, Int64(3500 * NSEC_PER_SEC)), dispatch_get_main_queue()) { call() } 23
  24. // Swift 3 let queue = DispatchQueue( label: "my.queue", attributes:

    .concurrent) queue.async { doHeavyWork() DispatchQueue.main.async { updateUI() } } let time = DispatchTime.now() + 3.5 DispatchQueue.main.after(when: time) { call() } // Also for group, semaphore, IO etc. 24
  25. Not only GCD... // Swift 2 func rotationAround(offset: CGPoint, angle:

    CGFloat, transform: CGAffineTransform = CGAffineTransformIdentity) -> CGAffineTransform { var result = CGAffineTransformTranslate(transform, offset.x, offset.y) result = CGAffineTransformRotate(result, angle) return CGAffineTransformTranslate(result, -offset.x, -offset.y) } 25
  26. // Swift 2 func rotationAround(offset: CGPoint, angle: CGFloat, transform: CGAffineTransform

    = CGAffineTransformIdentity) -> CGAffineTransform { var result = CGAffineTransformTranslate(transform, offset.x, offset.y) result = CGAffineTransformRotate(result, angle) return CGAffineTransformTranslate(result, -offset.x, -offset.y) } // Swift 3 func rotationAround(offset: CGPoint, angle: CGFloat, transform: CGAffineTransform = .identity) -> CGAffineTransform { return transform.translateBy(x: offset.x, y: offset.y) .rotate(angle) .translateBy(x: -offset.x, y: -offset.y) } 26
  27. // Swift 2 func trace(in context: CGContext, path: CGPath) {

    let red = CGColorCreateGenericRGB(1, 0, 0, 1) CGContextSaveGState(context) CGContextAddPath(context, path) CGContextSetStrokeColorWithColor(context, red) CGContextStrokePath(context) CGContextRestoreGState(context) } // Swift 3 func trace(in context: CGContext, path: CGPath) { let red = CGColor.red context.saveGState() context.addPath(path) context.setStrokeColor(red) context.strokePath() context.restoreGState() } 27
  28. Imported by Compiler from C No Runtime Overhead 28

  29. From Swift 2 To 3 Just forget the legacy C

    Difficulty: ! 29
  30. SE-0069 Mutability and Foundation Value Types SE-0086 Drop NS Prefix

    in Swift Foundation 30
  31. Value Type is Good 31

  32. Value Type is Good • Immutability • Less State •

    Performance 32
  33. Struct • String • Array Class • NSURL • NSDate

    • NSData 33
  34. Swift 3 All NS prefix removed: • NSURL → URL

    • NSDate → Date • NSData → Data • etc. From Class to Struct. Not an NSObject anymore. 34
  35. public struct URL : ReferenceConvertible, CustomStringConvertible, Equatable { public typealias

    ReferenceType = NSURL //... } • Reference type underneath • Value Semantic • Copy-on-Write 35
  36. Still be a class: • NSNotificationCenter → NotificationCenter • NSUserDefaults

    → UserDefaults • etc. 36
  37. From Swift 2 To 3 No NS prefix needed Difficulty:

    ! 37
  38. SE-0046 Establish consistent label behavior across all parameters including first

    labels 38
  39. Swift 2 The first label is omitted by default. func

    foo(a: T, b: U, c: V) { } foo(a, b: b, c: c) 39
  40. Swift 3 You need to write the first label by

    default: func foo(a: T, b: U, c: V) { } foo(a: a, b: b, c: c) 40
  41. Swift 3 Back compatibility Your current API will be imported

    as: func foo(_ a: T, b: U, c: V) { } But you should consider in Swift 3 way and give it a fix. 41
  42. SE-0004 Remove the ++ and -- operators 42

  43. let a = ++x // Plus self (x), then use

    let b = x++ // Use, then plus let c = --x // Minus, then use let d = x-- // Use, then minus 43
  44. let a = ++x // Plus self (x), then use

    let b = x++ // Use, then plus let c = --x // Minus, then use let d = x-- // Use, then minus var i = 0 if shouldCount { i++ } 44
  45. let a = ++x // Plus self (x), then use

    let b = x++ // Use, then plus let c = --x // Minus, then use let d = x-- // Use, then minus (i++)+(++i)+(++i)+(i++)+(i++) = ? // Good luck! 45
  46. From Swift 2 To 3 Stop using ++ and --

    Use += instead var i = 0 if shouldCount { i += 1 } Difficulty: ! 46
  47. SE-0025 Scoped Access Level 47

  48. Swift 2 public internal private ← current file 48

  49. Swift 3 public internal fileprivate ← current file private 49

  50. Swift 3 public internal fileprivate private ← current scope 50

  51. // Sample.swift struct MyStruct { private var name: String? func

    sayHello() { print("How are you?") } private func damnIt() { print("Damn you!") } // Cannot use `sayMorning` } extention MyStruct { // Cannot use `damnIt` and `name` private func sayMorning() { print("Morning!") sayHello() } } 51
  52. From Swift 2 To 3 Rename private to fileprivate Use

    private when really needed Difficulty: ! 52
  53. SE-0047 Defaulting non-Void functions so they warn on unused results

    53
  54. In Swift 2 @warn_unused_result(mutable_variant="sortInPlace") public func sort() -> [Self.Generator.Element] 54

  55. In Swift 3 @discardableResult func youCanIgnoreTheReturnValue() -> Int From Swift

    2 To 3 Use @discardableResult according to compile warning. Difficulty: ! 55
  56. Bad News 56

  57. • Full of breaking changes • From beginner to expert,

    again • Third party support 57
  58. Good News 58

  59. Xcode 8 contains both Swift 2.3 and Swift 3 59

  60. Is it worth upgrading to Swift 3? 60

  61. It depends. 61

  62. Thanks 62