Migrate Swift 4.2 to 5.2

30682a28206e455a1bc57d7d85cd1e14?s=47 Sho Masegi
September 20, 2020

Migrate Swift 4.2 to 5.2

30682a28206e455a1bc57d7d85cd1e14?s=128

Sho Masegi

September 20, 2020
Tweet

Transcript

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

    #d ShoMasegi
  2. About me Sho Masegi @boc_sho @ShoMasegi Money Forward

  3. ͯ͞ɺ

  4. 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
  5. • Result • Ordered Collection Diffing • Opaque Types •

    Property Wrappers • etc…. Swift 5.x features
  6. 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
  7. • Swift 5.xͷػೳΛ͋·Γ೺Ѳग़དྷ͍ͯͳ͍ํ • Swift 5.xͰϦϦʔε͞ΕͨػೳΛৼΓฦΓ͍ͨํ Target

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

  9. Swift 5.xͷओཁͳػೳͷ֓ཁͱ༻్ • Result • Ordered Collection Diffing • Opaque

    Return Types • Property Wrappers Agenda
  10. Result

  11. “success” / “failure” 2ύλʔϯ͚ͩΛ΋ͭenum ࣦഊ͢ΔՄೳੑ͕͋Δॲཧͷ ໭Γ஋΍ίʔϧόοΫͰ࢖༻͢Δ Result public enum Result<Success,

    Failure: Error> { case success(Success) case failure(Failure) } public func map<NewSuccess>( _ transform: (Success) -> NewSuccess ) -> Result<NewSuccess, Failure> { ... } public func mapError<NewFailure>( _ transform: (Failure) -> NewFailure ) -> Result<Success, NewFailure> { ... } public func flatMap<NewSuccess>( _ transform: (Success) -> Result<NewSuccess, Failure> ) -> Result<NewSuccess, Failure> { ... } public func flatMapError<NewFailure>( _ transform: (Failure) -> Result<Success, NewFailure> ) -> Result<Success, NewFailure> { ... }
  12. “success”࣌ʹฦ͢ ஋΍ͦͷܕΛม׵͢Δ Result // // public func map<NewSuccess>( // _

    transform: (Success) -> NewSuccess // ) -> Result<NewSuccess, Failure> // let result: Result<[Item], Error> let newResult = result.map { items -> [Section] in return makeSections(from: items) }
  13. “success”࣌ʹ ผͷResultܕʹม׵͢Δ “success”࣌ʹ Optionalͳ஋ΛͱΔ Result͔Β Non Optionalͳ஋ΛͱΔ Resultʹม׵ Result //

    // public func flatMap<NewSuccess>( // _ transform: (Success) -> Result<NewSuccess, Failure> // ) -> Result<NewSuccess, Failure> // let result: Result<Item?, Error> let newResult = result.flatMap { item -> Result<Item, Error> in if let item = item { return .success(item) } else { return .failure(CustomError.requiredIsNil) } }
  14. Ordered Collection Diffing

  15. Standard Libraryʹ ௥Ճ͞Εͨ Collectionͷࠩ෼Λ ܭࢉ͢Δfunction @available(swift, introduced: 5.1) extension BidirectionalCollection

    { public func difference<C>( from other: C, by areEquivalent: (Element, C.Element) -> Bool ) -> CollectionDifference<Element> where ... } extension BidirectionalCollection where Element: Equatable { public func difference<C>( from other: C ) -> CollectionDifference<Element> where ... } Ordered Collection Diffing
  16. CollectionDifference͸ ࡟আͱૠೖͷ2ύλʔϯͷ EnumͰߏ੒͞Ε͍ͯΔ @available(swift, introduced: 5.1) public struct CollectionDifference<ChangeElement> {

    public enum Change { case insert(offset: Int, element: ChangeElement, associatedWith: Int?) case remove(offset: Int, element: ChangeElement, associatedWith: Int?) } ... } Ordered Collection Diffing
  17. ΍ͬͱඪ४Ͱࠩ෼ܭࢉ͕ ࣮૷͞Εͨʂ

  18. UITableView΍UICollectionView Ͱ࢖͓͏ʂ

  19. None
  20. DiffableDataSourceΛ ࢖͍·͠ΐ͏ʂ

  21. Diffable Data Sources • UITableViewDiffableDataSource • UICollectionViewDiffableDataSource • NSCollectionViewDiffableDataSourceReference

  22. 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
  23. Opaque types

  24. ௚༁: “ෆಁ໌ͳܕ” 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
  25. • Triangle • Square • Pentagon // Protocol types func

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

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

    makeShape() -> Shape 
 
 // Opaque types func makeSomeShape() -> some Shape Opaque types • Circle • Ellipse Shape
  28. ͳΔ΄Ͳʁʁ

  29. ͳʹ͕خ͍͠ͷʁʁ

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

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

    types
  32. • Protocolʹassociated type͕͍͍ͭͯͯ΋ܕΛࢦఆͤͣʹ஋Λฦ ͤΔ Opaque types protocol GameObject { associatedtype

    Shape var shape: Shape { get } } func makeGameObject() -> GameObject { ... } // Compile Error func makeSomeGameObject() -> some GameObject { ... } // OK
  33. • Protocolʹassociated type͕͍͍ͭͯͯ΋ܕΛࢦఆͤͣʹ஋Λฦ ͤΔ • function (property)ࣗମ͕”ந৅తͳܕ”ͷ࣮ଶΛࢦఆͰ͖Δ • Φʔόʔϔουແ͘”ந৅తͳܕ”Λએݴग़དྷΔ Opaque

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

    types
  35. • function (property)ࣗମ͕”ந৅తͳܕ”ͷ࣮ଶΛࢦఆͰ͖Δ Opaque types func generic<T: Shape>() -> T

    { ... } let r: Rectangle = generic() // ݺͼग़͠ଆ͕࣮ଶΛࢦఆ͍ͯ͠Δ let c: Circle = generic() func reverseGeneric() -> some Shape { return Rectangle(...) } let s = reverseGeneric()// function͕࣮ଶΛࢦఆ͍ͯ͠Δ
  36. • Protocolʹassociated type͕͍͍ͭͯͯ΋ܕΛࢦఆͤͣʹ஋Λฦ ͤΔ • function (property)ࣗମ͕”ந৅తͳܕ”ͷ࣮ଶΛࢦఆͰ͖Δ • Φʔόʔϔουແ͘”ந৅తͳܕ”Λએݴग़དྷΔ Opaque

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

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

    types
  40. ͳΔ΄Ͳ

  41. Ͳ͜Ͱ࢖͏ͷʁʁ

  42. Swift UI

  43. 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() } } }
  44. Opaque types struct LandmarkRow: View { var landmark: Landmark var

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

    body: HStack<TuppleView<(Image, Text, Spacer, Text)>> { HStack { landmark.image .resizable() .frame(width: 50, height: 50) Text(landmark.name) Spacer() Text(landmark.id) } } }
  46. 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() } } }
  47. 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() } } }
  48. 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() } } }
  49. 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() } } }
  50. 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() } } }
  51. 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() } } }
  52. Property Wrapper

  53. ϓϩύςΟ΁ͷΞΫηεํ๏Λ ಠࣗʹఆٛ͢Δ͜ͱ͕ग़དྷΔ࢓૊Έ ಠࣗͷ 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"
  54. ࡞Γํ 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"
  55. @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
  56. ࡞Γํ 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
  57. ࡞Γํ 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
  58. GenericsΛ࢖ͬͯwrappedValueͷܕΛ ҙਤͨ͠΋ͷʹࢦఆ͢Δ͜ͱ΋Մೳ @propertyWrapper struct Atomic<Value> { private var value: Value

    init(wrappedValue: Value) { self.value = wrappedValue } var wrappedValue: Value { get { return load() } set { store(newValue: newValue) } } ... } Property Wrapper
  59. ۩ମྫ

  60. Property Wrapper - UserDefaults @propertyWrapper struct UserDefault<T> { 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) } } }
  61. Property Wrapper - Dependency Injection @propertyWrapper struct Inject<Component> { 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
  62. ·ͱΊ

  63. Swift 5.xͷओཁͳػೳͱ༻్ • Result • Ordered Collection Diffing • Opaque

    Types • Property Wrappers ·ͱΊ
  64. 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
  65. https://swift.org/

  66. ͋Γ͕ͱ͏͍͟͝·ͨ͠