Slide 1

Slide 1 text

Migrate Swift 4.2 to 5.2 iOSDC 2020 09/20(Sun) 15:40-16:00 #iosdc #d ShoMasegi

Slide 2

Slide 2 text

About me Sho Masegi @boc_sho @ShoMasegi Money Forward

Slide 3

Slide 3 text

ͯ͞ɺ

Slide 4

Slide 4 text

Swift versions Swift 5.0 Swift 5.1 Swift 5.2 Swift 5.3 Swift 6.0? 2019/03/25 2019/09/19 2020/03/24 2020/09/?? 2020/??/?? • Xcode 11.0 • SwiftUI • Combine • Xcode 10.2 • Xcode 11.4 • Xcode 12 • Xcode 12.x ? • async / await

Slide 5

Slide 5 text

• Result • Ordered Collection Diffing • Opaque Types • Property Wrappers • etc…. Swift 5.x features

Slide 6

Slide 6 text

Swift versions Swift 6.0? • Xcode 12.x ? • async / await Swift 5.0 Swift 5.1 Swift 5.2 2019/03/25 2019/09/19 2020/03/24 2020/??/?? • Xcode 11.0 • SwiftUI • Combine • Xcode 10.2 • Xcode 11.4 Swift 5.3 2020/09/?? • Xcode 12

Slide 7

Slide 7 text

• Swift 5.xͷػೳΛ͋·Γ೺Ѳग़དྷ͍ͯͳ͍ํ • Swift 5.xͰϦϦʔε͞ΕͨػೳΛৼΓฦΓ͍ͨํ Target

Slide 8

Slide 8 text

• Swift 5.xͰϦϦʔε͞Εͨػೳ͕ͳΜͱͳ͘Θ͔ͬͨঢ়ଶ • Swift 5.xͰϦϦʔε͞ΕͨػೳΛ೔ৗۀ຿ʹಋೖ͢Δ४උ͕ग़དྷͨ ঢ়ଶ Goal

Slide 9

Slide 9 text

Swift 5.xͷओཁͳػೳͷ֓ཁͱ༻్ • Result • Ordered Collection Diffing • Opaque Return Types • Property Wrappers Agenda

Slide 10

Slide 10 text

Result

Slide 11

Slide 11 text

“success” / “failure” 2ύλʔϯ͚ͩΛ΋ͭenum ࣦഊ͢ΔՄೳੑ͕͋Δॲཧͷ ໭Γ஋΍ίʔϧόοΫͰ࢖༻͢Δ Result public enum Result { case success(Success) case failure(Failure) } public func map( _ transform: (Success) -> NewSuccess ) -> Result { ... } public func mapError( _ transform: (Failure) -> NewFailure ) -> Result { ... } public func flatMap( _ transform: (Success) -> Result ) -> Result { ... } public func flatMapError( _ transform: (Failure) -> Result ) -> Result { ... }

Slide 12

Slide 12 text

“success”࣌ʹฦ͢ ஋΍ͦͷܕΛม׵͢Δ Result // // public func map( // _ transform: (Success) -> NewSuccess // ) -> Result // let result: Result<[Item], Error> let newResult = result.map { items -> [Section] in return makeSections(from: items) }

Slide 13

Slide 13 text

“success”࣌ʹ ผͷResultܕʹม׵͢Δ “success”࣌ʹ Optionalͳ஋ΛͱΔ Result͔Β Non Optionalͳ஋ΛͱΔ Resultʹม׵ Result // // public func flatMap( // _ transform: (Success) -> Result // ) -> Result // let result: Result let newResult = result.flatMap { item -> Result in if let item = item { return .success(item) } else { return .failure(CustomError.requiredIsNil) } }

Slide 14

Slide 14 text

Ordered Collection Diffing

Slide 15

Slide 15 text

Standard Libraryʹ ௥Ճ͞Εͨ Collectionͷࠩ෼Λ ܭࢉ͢Δfunction @available(swift, introduced: 5.1) extension BidirectionalCollection { public func difference( from other: C, by areEquivalent: (Element, C.Element) -> Bool ) -> CollectionDifference where ... } extension BidirectionalCollection where Element: Equatable { public func difference( from other: C ) -> CollectionDifference where ... } Ordered Collection Diffing

Slide 16

Slide 16 text

CollectionDifference͸ ࡟আͱૠೖͷ2ύλʔϯͷ EnumͰߏ੒͞Ε͍ͯΔ @available(swift, introduced: 5.1) public struct CollectionDifference { public enum Change { case insert(offset: Int, element: ChangeElement, associatedWith: Int?) case remove(offset: Int, element: ChangeElement, associatedWith: Int?) } ... } Ordered Collection Diffing

Slide 17

Slide 17 text

΍ͬͱඪ४Ͱࠩ෼ܭࢉ͕ ࣮૷͞Εͨʂ

Slide 18

Slide 18 text

UITableView΍UICollectionView Ͱ࢖͓͏ʂ

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

DiffableDataSourceΛ ࢖͍·͠ΐ͏ʂ

Slide 21

Slide 21 text

Diffable Data Sources • UITableViewDiffableDataSource • UICollectionViewDiffableDataSource • NSCollectionViewDiffableDataSourceReference

Slide 22

Slide 22 text

Ordered Collection Diffing • ʲSwiftʳ Swift5.1ͷ৽ػೳ Ordered Collection Diffingೖ໳ https://qiita.com/shiz/items/0e363219a0151d790d03 Diffable Data Sources • ࣌୅ͷมԽʹԠͯ͡ਐԽ͢ΔCollectionView ~Compositional LayoutsͱDiffable Data Sources~ https://qiita.com/shiz/items/a6032543a237bf2e1d19 References

Slide 23

Slide 23 text

Opaque types

Slide 24

Slide 24 text

௚༁: “ෆಁ໌ͳܕ” ProtocolͷΑ͏ͳܕΛந৅తʹѻ͑ΔΑ ͏ʹ͢Δ΋ͷ ”some Shape”ͷΑ͏ʹ࢖༻ͯ͠ ”Shape”Λܧঝͨ͋͠ΔҰͭͷܕΛࣔ͢ // Opaque types func makeSomeShape() -> some Shape { return Triangle(size: 1) } // Not Opaque types (Protocol Types) func makeShape() -> Shape { return Circle(diameter: 2) } protocol Shape { } struct Triangle: Shape { ... } struct Circle: Shape { ... } Opaque types

Slide 25

Slide 25 text

• Triangle • Square • Pentagon // Protocol types func makeShape() -> Shape 
 
 // Opaque types func makeSomeShape() -> some Shape Opaque types • Circle • Ellipse Shape

Slide 26

Slide 26 text

• Triangle • Square • Pentagon // Protocol types func makeShape() -> Shape 
 
 // Opaque types func makeSomeShape() -> some Shape Opaque types • Circle • Ellipse Shape

Slide 27

Slide 27 text

• Triangle • Square • Pentagon // Protocol types func makeShape() -> Shape 
 
 // Opaque types func makeSomeShape() -> some Shape Opaque types • Circle • Ellipse Shape

Slide 28

Slide 28 text

ͳΔ΄Ͳʁʁ

Slide 29

Slide 29 text

ͳʹ͕خ͍͠ͷʁʁ

Slide 30

Slide 30 text

• Protocolʹassociated type͕͍͍ͭͯͯ΋ܕΛࢦఆͤͣʹ஋Λฦ ͤΔ • function (property)ࣗମ͕”ந৅తͳܕ”ͷ࣮ଶΛࢦఆͰ͖Δ • Φʔόʔϔουແ͘”ந৅తͳܕ”Λએݴग़དྷΔ Opaque types

Slide 31

Slide 31 text

• Protocolʹassociated type͕͍͍ͭͯͯ΋ܕΛࢦఆͤͣʹ஋Λฦ ͤΔ • function (property)ࣗମ͕”ந৅తͳܕ”ͷ࣮ଶΛࢦఆͰ͖Δ • Φʔόʔϔουແ͘”ந৅తͳܕ”Λએݴग़དྷΔ Opaque types

Slide 32

Slide 32 text

• Protocolʹassociated type͕͍͍ͭͯͯ΋ܕΛࢦఆͤͣʹ஋Λฦ ͤΔ Opaque types protocol GameObject { associatedtype Shape var shape: Shape { get } } func makeGameObject() -> GameObject { ... } // Compile Error func makeSomeGameObject() -> some GameObject { ... } // OK

Slide 33

Slide 33 text

• Protocolʹassociated type͕͍͍ͭͯͯ΋ܕΛࢦఆͤͣʹ஋Λฦ ͤΔ • function (property)ࣗମ͕”ந৅తͳܕ”ͷ࣮ଶΛࢦఆͰ͖Δ • Φʔόʔϔουແ͘”ந৅తͳܕ”Λએݴग़དྷΔ Opaque types

Slide 34

Slide 34 text

• Protocolʹassociated type͕͍͍ͭͯͯ΋ܕΛࢦఆͤͣʹ஋Λฦ ͤΔ • function (property)ࣗମ͕”ந৅తͳܕ”ͷ࣮ଶΛࢦఆͰ͖Δ • Φʔόʔϔουແ͘”ந৅తͳܕ”Λએݴग़དྷΔ Opaque types

Slide 35

Slide 35 text

• function (property)ࣗମ͕”ந৅తͳܕ”ͷ࣮ଶΛࢦఆͰ͖Δ Opaque types func generic() -> T { ... } let r: Rectangle = generic() // ݺͼग़͠ଆ͕࣮ଶΛࢦఆ͍ͯ͠Δ let c: Circle = generic() func reverseGeneric() -> some Shape { return Rectangle(...) } let s = reverseGeneric()// function͕࣮ଶΛࢦఆ͍ͯ͠Δ

Slide 36

Slide 36 text

• Protocolʹassociated type͕͍͍ͭͯͯ΋ܕΛࢦఆͤͣʹ஋Λฦ ͤΔ • function (property)ࣗମ͕”ந৅తͳܕ”ͷ࣮ଶΛࢦఆͰ͖Δ • Φʔόʔϔουແ͘”ந৅తͳܕ”Λએݴग़དྷΔ Opaque types

Slide 37

Slide 37 text

• Protocolʹassociated type͕͍͍ͭͯͯ΋ܕΛࢦఆͤͣʹ஋Λฦ ͤΔ • function (property)ࣗମ͕”ந৅తͳܕ”ͷ࣮ଶΛࢦఆͰ͖Δ • Φʔόʔϔουແ͘”ந৅తͳܕ”Λએݴग़དྷΔ Opaque types

Slide 38

Slide 38 text

• Φʔόʔϔουແ͘”ந৅తͳܕ”Λએݴग़དྷΔ Opaque types let triangle: Triangle = Triangle() MemoryLayout.size(ofValue: triangle) // 1 let square: Square = Square() MemoryLayout.size(ofValue: square) // 8 var shape: Shape = Triangle() MemoryLayout.size(ofValue: shape) // 40 var someShape: some Shape = Triangle() MemoryLayout.size(ofValue: someShape) // 1

Slide 39

Slide 39 text

• Protocolʹassociated type͕͍͍ͭͯͯ΋ܕΛࢦఆͤͣʹ஋Λฦ ͤΔ • function (property)ࣗମ͕”ந৅తͳܕ”ͷ࣮ଶΛࢦఆͰ͖Δ • Φʔόʔϔουແ͘”ந৅తͳܕ”Λએݴग़དྷΔ Opaque types

Slide 40

Slide 40 text

ͳΔ΄Ͳ

Slide 41

Slide 41 text

Ͳ͜Ͱ࢖͏ͷʁʁ

Slide 42

Slide 42 text

Swift UI

Slide 43

Slide 43 text

Opaque types struct LandmarkRow: View { var landmark: Landmark var body: some View { HStack { landmark.image .resizable() .frame(width: 50, height: 50) Text(landmark.name) Spacer() } } }

Slide 44

Slide 44 text

Opaque types struct LandmarkRow: View { var landmark: Landmark var body: HStack> { HStack { landmark.image .resizable() .frame(width: 50, height: 50) Text(landmark.name) Spacer() } } }

Slide 45

Slide 45 text

Opaque types struct LandmarkRow: View { var landmark: Landmark var body: HStack> { HStack { landmark.image .resizable() .frame(width: 50, height: 50) Text(landmark.name) Spacer() Text(landmark.id) } } }

Slide 46

Slide 46 text

Opaque types struct LandmarkRow: View { var landmark: Landmark var body: some View { HStack { landmark.image .resizable() .frame(width: 50, height: 50) Text(landmark.name) Spacer() } } }

Slide 47

Slide 47 text

Opaque types struct LandmarkRow: View { var landmark: Landmark var body: some View { HStack { landmark.image .resizable() .frame(width: 50, height: 50) Text(landmark.name) Spacer() } } }

Slide 48

Slide 48 text

Opaque types struct LandmarkRow: View { var landmark: Landmark var body: some View { HStack { landmark.image .resizable() .frame(width: 50, height: 50) Text(landmark.name) Spacer() } } }

Slide 49

Slide 49 text

Opaque types struct LandmarkRow: View { var landmark: Landmark var body: some View { HStack { landmark.image .resizable() .frame(width: 50, height: 50) Text(landmark.name) Text(landmark.id) Spacer() } } }

Slide 50

Slide 50 text

Opaque types struct LandmarkRow: View { var landmark: Landmark var body: some View { HStack { landmark.image .resizable() .frame(width: 50, height: 50) Text(landmark.name) Spacer() } } }

Slide 51

Slide 51 text

Opaque types struct LandmarkRow: View { var landmark: Landmark var body: some View { HStack { landmark.image .resizable() .frame(width: 50, height: 50) Text(landmark.name) Spacer() } } }

Slide 52

Slide 52 text

Property Wrapper

Slide 53

Slide 53 text

ϓϩύςΟ΁ͷΞΫηεํ๏Λ ಠࣗʹఆٛ͢Δ͜ͱ͕ग़དྷΔ࢓૊Έ ಠࣗͷ getter / setter Λڞ௨Խग़དྷΔ wrappedValueͷ getter / setter Λ ࣮૷͢Δ͜ͱͰಠࣗͷΞΫηεํ๏Λ ఆٛ͢Δ Property Wrapper @propertyWrapper struct ForcedUpperCase { private var upperCased: String = "" private var wrappedValue: String { get { return upperCased } set { upperCased = newValue.uppercased() } } } @ForcedUpperCase var string: String string = "uppercase" // string = “UPPERCASE"

Slide 54

Slide 54 text

࡞Γํ Property Wrapper @propertyWrapper struct ForcedUpperCase { private var upperCased: String = "" private var wrappedValue: String { get { return upperCased } set { upperCased = newValue.uppercased() } } } @ForcedUpperCase var string: String string = "uppercase" // string = “UPPERCASE"

Slide 55

Slide 55 text

@propertyWrapper struct ForcedUpperCase { private var upperCased: String = "" private var wrappedValue: String { get { return upperCased } set { upperCased = newValue.uppercased() } } } @ForcedUpperCase var string: String string = "uppercase" // string = “UPPERCASE" ࡞Γํ 1. @propertyWrapperΛ struct / class / enumʹ͚ͭΔ Property Wrapper

Slide 56

Slide 56 text

࡞Γํ 1. @propertyWrapperΛ struct / class / enumʹ͚ͭΔ 2. wrappedValueϓϩύςΟΛఆٛ͠ getter / setter Λ࣮૷͢Δ @propertyWrapper struct ForcedUpperCase { private var upperCased: String = "" private var wrappedValue: String { get { return upperCased } set { upperCased = newValue.uppercased() } } } @ForcedUpperCase var string: String string = "uppercase" // string = “UPPERCASE" Property Wrapper

Slide 57

Slide 57 text

࡞Γํ 1. @propertyWrapperΛ struct / class / enumʹ͚ͭΔ 2. wrappedValueϓϩύςΟΛఆٛ͠ getter / setter Λ࣮૷͢Δ ͚ͩʂʂ @propertyWrapper struct ForcedUpperCase { private var upperCased: String = "" private var wrappedValue: String { get { return upperCased } set { upperCased = newValue.uppercased() } } } @ForcedUpperCase var string: String string = "uppercase" // string = “UPPERCASE" Property Wrapper

Slide 58

Slide 58 text

GenericsΛ࢖ͬͯwrappedValueͷܕΛ ҙਤͨ͠΋ͷʹࢦఆ͢Δ͜ͱ΋Մೳ @propertyWrapper struct Atomic { private var value: Value init(wrappedValue: Value) { self.value = wrappedValue } var wrappedValue: Value { get { return load() } set { store(newValue: newValue) } } ... } Property Wrapper

Slide 59

Slide 59 text

۩ମྫ

Slide 60

Slide 60 text

Property Wrapper - UserDefaults @propertyWrapper struct UserDefault { let key: String let defaultValue: T var wrappedValue: T { get { return UserDefaults.standard.object(forKey: key) as? T ?? defaultValue } set { UserDefaults.standard.set(newValue, forKey: key) } } }

Slide 61

Slide 61 text

Property Wrapper - Dependency Injection @propertyWrapper struct Inject { var component: Component init(){ self.component = Resolver.shared.resolve(Component.self) } public var wrappedValue:Component { get { return component} mutating set { component = newValue } } } From https://medium.com/swlh/dependency-injection-in-swift-with-property-wrappers-c1f02f06cd51

Slide 62

Slide 62 text

·ͱΊ

Slide 63

Slide 63 text

Swift 5.xͷओཁͳػೳͱ༻్ • Result • Ordered Collection Diffing • Opaque Types • Property Wrappers ·ͱΊ

Slide 64

Slide 64 text

Swift versions Swift 6.0? • Xcode 12.x ? • async / await Swift 5.0 Swift 5.1 Swift 5.2 2019/03/25 2019/09/19 2020/03/24 2020/??/?? • Xcode 11.0 • SwiftUI • Combine • Xcode 10.2 • Xcode 11.4 Swift 5.3 2020/09/?? • Xcode 12

Slide 65

Slide 65 text

https://swift.org/

Slide 66

Slide 66 text

͋Γ͕ͱ͏͍͟͝·ͨ͠