Slide 1

Slide 1 text

SP TF JP20028 - onevcat Wei Wang 1

Slide 2

Slide 2 text

Recently 2

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

Open + Evolution 5

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

7

Slide 8

Slide 8 text

Important proposals & Broken APIs 8

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

Problems of Current Cocoa APIs • Disordered • Verbose & Duplicated • For Objective-C. Not Swifty 10

Slide 11

Slide 11 text

Clarity let text = "Hello world" text.stringByAppendingString(", Swift2") 11

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

More Examples var array = [1, 2, 3, 4] //Swift 2 array.removeAtIndex(1) // Swift 3 array.remove(at: 1) 17

Slide 18

Slide 18 text

More Examples let text = "abcde" // Swift 2 text.stringByReplacingOccurrencesOfString( "abc", withString: "123") // Swift 3 text.replacingOccurrences( of: "abc", with: "123") 18

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

From Swift 2 To 3 Get to be used to new APIs With Swift migrator Difficulty: ! 21

Slide 22

Slide 22 text

SE-0088 Modernize libdispatch for Swift 3 naming conventions 22

Slide 23

Slide 23 text

// 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

Slide 24

Slide 24 text

// 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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

// 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

Slide 27

Slide 27 text

// 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

Slide 28

Slide 28 text

Imported by Compiler from C No Runtime Overhead 28

Slide 29

Slide 29 text

From Swift 2 To 3 Just forget the legacy C Difficulty: ! 29

Slide 30

Slide 30 text

SE-0069 Mutability and Foundation Value Types SE-0086 Drop NS Prefix in Swift Foundation 30

Slide 31

Slide 31 text

Value Type is Good 31

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

Struct • String • Array Class • NSURL • NSDate • NSData 33

Slide 34

Slide 34 text

Swift 3 All NS prefix removed: • NSURL → URL • NSDate → Date • NSData → Data • etc. From Class to Struct. Not an NSObject anymore. 34

Slide 35

Slide 35 text

public struct URL : ReferenceConvertible, CustomStringConvertible, Equatable { public typealias ReferenceType = NSURL //... } • Reference type underneath • Value Semantic • Copy-on-Write 35

Slide 36

Slide 36 text

Still be a class: • NSNotificationCenter → NotificationCenter • NSUserDefaults → UserDefaults • etc. 36

Slide 37

Slide 37 text

From Swift 2 To 3 No NS prefix needed Difficulty: ! 37

Slide 38

Slide 38 text

SE-0046 Establish consistent label behavior across all parameters including first labels 38

Slide 39

Slide 39 text

Swift 2 The first label is omitted by default. func foo(a: T, b: U, c: V) { } foo(a, b: b, c: c) 39

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

SE-0004 Remove the ++ and -- operators 42

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

From Swift 2 To 3 Stop using ++ and -- Use += instead var i = 0 if shouldCount { i += 1 } Difficulty: ! 46

Slide 47

Slide 47 text

SE-0025 Scoped Access Level 47

Slide 48

Slide 48 text

Swift 2 public internal private ← current file 48

Slide 49

Slide 49 text

Swift 3 public internal fileprivate ← current file private 49

Slide 50

Slide 50 text

Swift 3 public internal fileprivate private ← current scope 50

Slide 51

Slide 51 text

// 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

Slide 52

Slide 52 text

From Swift 2 To 3 Rename private to fileprivate Use private when really needed Difficulty: ! 52

Slide 53

Slide 53 text

SE-0047 Defaulting non-Void functions so they warn on unused results 53

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

In Swift 3 @discardableResult func youCanIgnoreTheReturnValue() -> Int From Swift 2 To 3 Use @discardableResult according to compile warning. Difficulty: ! 55

Slide 56

Slide 56 text

Bad News 56

Slide 57

Slide 57 text

• Full of breaking changes • From beginner to expert, again • Third party support 57

Slide 58

Slide 58 text

Good News 58

Slide 59

Slide 59 text

Xcode 8 contains both Swift 2.3 and Swift 3 59

Slide 60

Slide 60 text

Is it worth upgrading to Swift 3? 60

Slide 61

Slide 61 text

It depends. 61

Slide 62

Slide 62 text

Thanks 62