Save 37% off PRO during our Black Friday Sale! »

チームでSwiftUIを書くために / After Party iOSDC Japan 2021 SwiftUI

8db1f2958e24accef8412659656fc8dc?s=47 Atsuya Sato
October 01, 2021

チームでSwiftUIを書くために / After Party iOSDC Japan 2021 SwiftUI

2021/10/1に開催されたAfter Party iOSDC Japan 2021の登壇資料です

8db1f2958e24accef8412659656fc8dc?s=128

Atsuya Sato

October 01, 2021
Tweet

Transcript

  1. νʔϜͰSwiftUIΛॻͨ͘Ίʹ ~ಡΈ΍͘͢อक͠΍͍͢SwiftUIͷઃܭʹ͍ͭͯߟ͑ͨ͜ͱ~ After Party iOSDC Japan 2021 / Atsuya Sato

  2. ࠤ౻ ರ໵ (͋ͭ΍) @n_atmark • iOS / Android ΤϯδχΞ •

    ݱࡏ͸ΫοΫύουAndroidΞϓϦͷʮ͔͍΋ͷʯλϒΛӶҙ։ൃத 2019/04 2021/01 • ΫοΫύου৽ଔೖࣾ • ങ෺ࣄۀຊ෦ ങ෺ϓϩμΫτ։ൃ෦ • ΫοΫύουϚʔτͷྲྀ௨޲͚ͷαʔϏε։ൃɺϋʔυ΢ΣΞ։ൃͳͲʹैࣄ • ΫοΫύουࣄۀຊ෦ ങ෺αʔϏε։ൃ෦ • ΫοΫύουiOSΞϓϦͷʮ͔͍΋ͷʯλϒͷ։ൃʹैࣄ
  3. ΞδΣϯμ • എܠ • ։ൃ͍ͯ͠ΔϓϩμΫτͷ঺հ • νʔϜ΍ϓϩμΫτͷن໛ײ • SwiftUIΛ༻͍ͯ1೥ؒ։ൃͯ͠Έͯ •

    ಡΈ΍ͯ͘͢อक͠΍͍͢ઃܭʹ͍ͭͯߟ͑ͨࣄ • ౷Ұͨ͠ॻ͖ํͰϨΠΞ΢τΛઃܭ͢ΔͨΊʹ • ෳࡶɾଟ༷ͳ৚݅ʹରॲ͢Δ • ྑ͍ઃܭ΁ͷҙࣝΛνʔϜ΁ਁಁ͢ΔͨΊʹ • ·ͱΊ
  4. ։ൃ͍ͯ͠ΔϓϩμΫτͷ঺հ • എܠ • ։ൃ͍ͯ͠ΔϓϩμΫτͷ঺հ • νʔϜ΍ϓϩμΫτͷن໛ײ • SwiftUIΛ༻͍ͯ1೥ؒ։ൃͯ͠Έͯ

  5. ΫοΫύουΞϓϦʮങ͍෺ػೳʯͷ঺հ

  6. ΫοΫύουΞϓϦʮങ͍෺ػೳʯͷ঺հ

  7. ΫοΫύουΞϓϦʮങ͍෺ػೳʯͷ঺հ ৯ࡐ͔ΒϨγϐ͕୳ͤΔ ৯ࡐΛങͬͨਓ͕ ࣮ࡍʹ࡞ͬͨྉཧ ΛࢀߟʹͰ͖Δ

  8. ΫοΫύουΞϓϦʮങ͍෺ػೳʯͷ঺հ レシピから必要な⾷材 を購⼊できる

  9. νʔϜ΍ϓϩμΫτͷن໛ײ • എܠ • ։ൃ͍ͯ͠ΔϓϩμΫτͷ঺հ • νʔϜ΍ϓϩμΫτͷن໛ײ • SwiftUIΛ༻͍ͯ1೥ؒ։ൃͯ͠Έͯ

  10. νʔϜͱ։ൃ͍ͯ͠ΔϓϩμΫτʹ͍ͭͯ • ങ෺αʔϏε։ൃ෦ • ʮϨγϐʯ×ʮങ͍෺ʯʹΑͬͯ৽ͨͳՁ஋ΛੜΈ ग़͢௅ઓ • ΫοΫύουiOSΞϓϦͷʮങ͍෺ػೳʯ • ΤϯδχΞ6ਓ

    (iOS 3ɺαʔόʔαΠυ3) • + ඇఆظͰΠϯλʔϯੜ͕νʔϜʹδϣΠϯ
  11. ΫοΫύουΞϓϦʮങ͍෺ػೳʯͷ։ൃ • ϚϧνϞδϡʔϧԽ͞Ε͍ͯΔΫοΫύουΞϓϦͷ Feature ModuleͷҰͭͱͯ͠ػೳ։ൃ 
 (KaimonoϞδϡʔϧ)

  12. https://speakerdeck.com/giginet/da-gui-mo-naapurifalsemarutimoziyurugou-cheng-falseshi-jian ⼤規模なアプリのマルチモジュール構成の実践

  13. ΫοΫύουΞϓϦʮങ͍෺ػೳʯͷ։ൃ • ΄΅શͯSwiftUIͰ։ൃத • VIPERΞʔΩςΫνϟͷ͏ͪɺView෦෼ͷΈͰ SwiftUIΛར༻͢Δઃܭ

  14. https://techlife.cookpad.com/entry/2021/01/18/kaimono-swift-ui SwiftUI を活⽤した「レシピ」×「買い物」の新機能開発

  15. ΫοΫύουΞϓϦʮങ͍෺ػೳʯͷ։ൃ • Feature ModuleͷҰͭͱͯ͠ػೳ։ൃ • VIPERΞʔΩςΫνϟͷ͏ͪɺView෦෼ͷΈͰSwiftUI Λར༻͢Δઃܭ • 2020೥3݄͔Β։ൃ (2020೥10݄ʹҰൠϦϦʔε)

    • ࠷௿αϙʔτOS͸iOS 13.3
  16. ΫοΫύουΞϓϦʮങ͍෺ػೳʯͷ։ൃ • Kaimono Ϟδϡʔϧ഑Լͷίʔυߦ਺ • 45,953ߦ (ΫοΫύουiOSશମͷ໿15%) • UIHostingViewControllerͰϥοϓ͞ΕͨRootView •

    35ը໘ • ผϑΝΠϧʹ੾Γग़͞ΕͨSwiftUIίϯϙʔωϯτ • 149ݸ
  17. None
  18. SwiftUIΛ༻͍ͯ1೥ؒ։ൃͯ͠Έͯ • എܠ • ։ൃ͍ͯ͠ΔϓϩμΫτͷ঺հ • νʔϜ΍ϓϩμΫτͷن໛ײ • SwiftUIΛ༻͍ͯ1೥ؒ։ൃͯ͠Έͯ

  19. 1೥લͷঢ়گ • iOSDC Japan 2020Ͱൃදͨ͠λΠϛϯά … ͪΐ͏Ͳങ ͍෺ػೳϦϦʔε࣌ظͩͬͨ

  20. https://speakerdeck.com/yujif/iosdc-japan-2020-day-2-cookpad クックパッドが、⾰新的な⽅法でまったく新しい買い物体験を皆様にお届けします

  21. None
  22. 1೥લͷঢ়گ • SwiftUIͷϝϦοτΛײ͍ͯͨ͡෦෼ • ίʔυྔ͕ݮΔ • ෳࡶɾଟ༷ͳ৚݅ʹରͯ͠෼͔Γ΍͘͢ॻ͚Δ • ίϯϙʔωϯτ୯ҐͰ࢖͍ճ͠ɾվม͕͠΍͍͢

  23. ΞϓϦΛϦϦʔε͔ͯ͠Β1೥։ൃ͍ͯ͘͠தͰͷมԽ • ίʔυϕʔεͷڊେԽ • Feature ModuleͷதͰ͸ίʔυߦ਺΋VIPERγʔϯ਺΋࠷େʹ • iOS 14ɾiOS 15ͷϦϦʔε

    • iOS 13ɺ14ɺ15ͷ3όʔδϣϯαϙʔτʹ • νʔϜͷ֦େ • ϝΠϯͰ։ൃ͢ΔΤϯδχΞ΋૿͑ͨ • Πϯλʔϯੜ΋ܞΘΔΑ͏ʹ
  24. 1೥։ൃͯ͠Έͯײ͍ͯ͡Δ՝୊ • iOS 13ରԠʹΑΔফ໣͸গͳ͔Βͣൃੜ͢Δ • iOS 13͚ͩڍಈ͕ҧ͏෦෼͕গͳ͔Βͣ͋Δ • ύϑΥʔϚϯεΛ٘ਜ਼ʹ͍ͯ͠ΔՕॴ΋݁ߏ͋Δ •

    LazyV/HStackɺLazyV/HGrid͸࢖͑ͯͳ͍😢
  25. 1೥։ൃͯ͠Έͯײ͍ͯ͡Δ՝୊ • ॊೈੑ͕ߴ͍ͨΊɺUIͷ૊Έํ͕ਓʹΑͬͯมΘΔ • ྫ: ཁૉΛॏͶ͍ͨͱ͖ͷZStackɺbackgroundɺ overlayͷ࢖͍෼͚ • ྫ: εϖʔεͷ։͚ํ

    • ίϯϙʔωϯτ෼ׂͷཻ౓
  26. Q: ࠓޙ΋SwiftUIΛऔΓೖΕͨ։ൃ Λ͢Δʁ ৭ʑফ໣΋ ײͯͦ͡͏͚ͩͲ…?

  27. Q: ࠓޙ΋SwiftUIΛऔΓೖΕͨ։ൃ Λ͢Δʁ A: Yes

  28. ࠓޙ΋SwiftUIΛऔΓೖΕͨ։ൃΛ͢Δʁ ෆ֬ఆͳϢʔβʔମݧΛ͍ͪૣཱ֬͘͢ΔͨΊʹ ʮ࡞Γ΍͍͢ɾյ͠΍͍͢ʯͷ͸ॏཁ SwiftUIΛ࢖͏͜ͱͰ໌Β͔ʹ͜ͷ෦෼͸ૣ͘ͳ͍ͬͯΔ

  29. ࠓޙ΋SwiftUIΛऔΓೖΕͨ։ൃΛ͢Δʁ ࠓޙ΋νʔϜͰSwiftUIΛ࠾༻͍ͯͨ͘͠Ίʹ… SwiftUIΛ࢖ͬͯײ͍ͯ͡Δ՝୊Λ ҰͭͣͭऔΓআ͍͍͖͍ͯͨ💪

  30. ಡΈ΍ͯ͘͢อक͠΍͍͢ SwiftUIͷઃܭʹ͍ͭͯߟ͑Δ

  31. 今⽇のトピックでは取り扱いません

  32. αʔϏεಛੑΛߟ͑Δ • ʮ͔͍΋ͷʯλϒͷߏ੒͸جຊ͸ॎεΫϩʔϧͷը໘ • Viewߏஙͷࡍͷجຊܗͱͯ͠ScrollViewͷதʹཁૉ Λ٧Ί͍ͯ͘ը໘͕΄ͱΜͲ

  33. αʔϏεಛੑΛߟ͑Δ • ෳࡶଟ༷ͳঢ়ଶ • ྫ: ঎඼஫จޙͷड͚औΓʹؔ͢Δঢ়ଶ

  34. αʔϏεಛੑʹجͮ͘՝୊ • ը໘͕ॎʹ௕͘ͳΓ΍͍͢ • ίϯϙʔωϯτͷཻ౓΍ॻ ͖ํ͕౷Ұ͞Εͯͳ͍ͱಡ Έʹ͍͘ • ঢ়ଶ͕૿͑Δͱɺ෼ذ΋ͦͷ ෼૿͑Δ

  35. ಡΈ΍͘͢อक͠΍͍͢ઃܭ • ઃܭʹݸਓ͕ࠩ͋·Γग़ͳ͍Α͏ʹ͍ͨ͠ • ৚͕݅ෳࡶʹͳͬͯ΋ಡΊΔΑ͏ʹ͓͖͍ͯͨ͠ • ৚͕݅ෳࡶͳը໘ͷอकΛ༰қʹ͍ͨ͠ • ྑ͍ઃܭ΁ͷҙࣝΛνʔϜʹਁಁ͍ͤͨ͞

  36. ౷Ұͨ͠ॻ͖ํͰϨΠΞ΢τΛઃܭ͢ΔͨΊʹ • ಡΈ΍ͯ͘͢อक͠΍͍͢ઃܭʹ͍ͭͯߟ͑ͨࣄ ◦ ౷Ұͨ͠ॻ͖ํͰϨΠΞ΢τΛઃܭ͢ΔͨΊʹ ◦ ෳࡶɾଟ༷ͳ৚݅ʹରॲ͢Δ ◦ ྑ͍ઃܭ΁ͷҙࣝΛνʔϜ΁ਁಁ͢ΔͨΊʹ

  37. ౷Ұͨ͠ॻ͖ํͰϨΠΞ΢τΛઃܭ͢ΔͨΊʹ • RootViewͷbodyʹॻ͘΂͖಺༰Λఆ͍ٛͨ͠ • ίϯϙʔωϯτԽͷཻ౓ʹؔͯ͠ڞ௨ೝࣝΛͱΓ͍ͨ

  38. ϨΠΞ΢τ૊Έʹؔͯ͠ struct KaimonoCartView: View { var body: some View {

    ScrollView { orderDeliverySection cartPriceSection pickupNameSettingSection deliveryInformationSection pickupStepsSection } } }
  39. ϨΠΞ΢τ૊Έʹؔͯ͠ • ը໘Λҙຯͷ͋Δ·ͱ·ΓͰSectionʹ෼ׂ • ෳ਺ίϯϙʔωϯτΛͱΓ·ͱΊΔ • ίϯϙʔωϯτؒͷϚʔδϯௐ੔Λ 
 ߦ͏ͨΊͷϨΠϠʔ

  40. ϨΠΞ΢τ૊Έʹؔͯ͠ • ը໘Λҙຯͷ͋Δ·ͱ·ΓͰSectionʹ෼ׂ • ෼ׂͨ͠Section͸RootViewʹඥͮ͘ 
 (ෳ਺ը໘Ͱར༻͠ͳ͍) • SectionΛෳ਺ը໘Ͱ࢖͍ͨ͘ͳͬͨ ΒίϯϙʔωϯτԽͷཻ౓Λݟ௚͢

  41. Sectionͷ෼ׂҐஔͷܾΊํ • σβΠφʔͱ૬ஊ͠ͳ͕ΒηΫγϣϯ෼ׂҐஔ ΛܾΊΔΑ͏ʹ͢Δ • Figma্Ͱ΋σβΠϯελΠϧʹԊͬͯάϧʔ ϐϯά͞Ε͍ͯΔͷͰɺσβΠφʔͷҙਤΛ൓ өͭͭ͠Section෼ׂ

  42. None
  43. Atoms Molecules Moleculesͷू߹ମ Organisms ProductTile ProductsGrid PopularProductsSection

  44. ίϯϙʔωϯτʹؔͯ͠ • ίϯϙʔωϯτԽ͢Δ΋ͷʹؔͯ͠͸ผϑΝΠϧʹ੾Γग़͠ • ཻ౓ • ΞτϛοΫσβΠϯͰݴ͏Molecules • ୯ମMoleculesΛෳ਺ฒ΂ͨঢ়ଶͷ΋ͷ※ΛίϯϙʔωϯτԽ •

    AtomsϨϕϧͷίϯϙʔωϯτԽ͸ͯ͠·ͤΜ
  45. ίϯϙʔωϯτʹؔͯ͠ • ίϯϙʔωϯτͷཻ౓ʹؔͯ͠νʔϜ಺Ͱೝ͕ࣝऔΕ͍ͯΔͱί ϛϡχέʔγϣϯ͕ͱΓ΍͍͢ • Sectionͱͯ͠RootViewʹඥͮ͘ܗͰ༻ҙ͢΂͖΋ͷ • ίϯϙʔωϯτͱͯ͠੾Γग़͢΂͖΋ͷ • ίϯϙʔωϯτͱͯ͠੾Γग़͢৔߹

    • Ͳ͜·Ͱࡉ͔͘෼ׂ͢Δͷ͔
  46. ෳࡶɾଟ༷ͳ৚݅ʹରॲ͢Δ • ಡΈ΍ͯ͘͢อक͠΍͍͢ઃܭʹ͍ͭͯߟ͑ͨࣄ ◦ ౷Ұͨ͠ॻ͖ํͰϨΠΞ΢τΛઃܭ͢ΔͨΊʹ ◦ ෳࡶɾଟ༷ͳ৚݅ʹରॲ͢Δ ◦ ྑ͍ઃܭ΁ͷҙࣝΛνʔϜ΁ਁಁ͢ΔͨΊʹ

  47. ෳࡶɾଟ༷ͳ৚݅ʹରॲ͢Δ

  48. ෳࡶɾଟ༷ͳ৚݅ʹରॲ͢Δ struct KaimonoDeliveryDetailView: View { var body: some View {

    ScrollView { switch dataSource.delivery.deliveryStatus { case .accepting: headerSection pickupNameSection orderedProductsSection if shouldShowPickupGuide { pickupGuideSection } // Sectionͷτϧπϝ acceptedButtonSection ordersSection case .preparing: // ུ } } } }
  49. ෳࡶɾଟ༷ͳ৚݅ʹରॲ͢Δ • RootViewͷbodyʹSectionΛྻڍ͢ΔΑ͏ʹͨ͜͠ͱͰ ݟ௨͕͠ྑ͍ • ঢ়ଶʹԠͨ͡Sectionͷग़͠෼͚΍ɺಛఆ৚݅ʹԠ͡ ͨSectionͷτϧπϝ΋෼͔Γ΍͍͢ • body͕ը໘ϨΠΞ΢τͷઃܭਤͱͯ͠ػೳ͢Δ

  50. ਖ਼֬ʹಈ࡞ͤ͞ΔͨΊʹ • ίʔυ্Ͱͷݟ௨͠͸͠΍͘͢ͳ͕ͬͨ… • ෳ਺ͷ৚݅Λߟྀͨ͠ը໘ʹ͓͚ΔϢʔβʔঢ়ଶͷ࠶ݱ ͸೉͍͠ • ը໘͕յΕ͍ͯͳ͍͜ͱΛಈ࡞֬ೝ͢Δ • ࣮૷ʹೖΔ·Ͱʹ֘౰ը໘ΛදࣔͰ͖ΔΑ͏ʹͳΔ

    ·Ͱ͕͔͔࣌ؒΔ
  51. ਖ਼֬ʹಈ࡞ͤ͞ΔͨΊͷऔΓ૊Έ

  52. https://speakerdeck.com/aomathwift/ji-neng-gotonidong-zuo- suruminiapuridepurebiyusaikuruwobao-su-nisitahua 機能ごとに動作するミニアプリでプレビューサイクルを爆速にした話

  53. ਖ਼֬ʹಈ࡞ͤ͞ΔͨΊͷऔΓ૊Έ

  54. ਖ਼֬ʹಈ࡞ͤ͞ΔͨΊͷऔΓ૊Έ extension SandboxScene { static let kaimonoTopForJustSetupCompleted = SandboxScene(sceneName: "τοϓʢडऔ৔ॴઃఆࡁɾະ஫จʣ")

    { initializer in let environment = StubbableEnvironment() initializer.initialize(environment) environment.registerClientResponses(fixtures, overrideFixtures: [ .orders(.empty), .userOrderedDeliveries(.empty), ]) ɹ let viewController = KaimonoTopViewBuilder.build(environment: environment) return viewController } static let kaimonoTopForDeliveriesUnavailable = SandboxScene(sceneName: "τοϓʢ௚ۙͷ഑ૹͳ͠ʣ") { initializer in // ུ } } private let fixtures: [Fixture] = [ .cart(.normal), .promotedDeliveryProducts(.ordinary), .me(.userLocation), .feature(.popularProducts), // ུ ]
  55. ਖ਼֬ʹಈ࡞ͤ͞ΔͨΊͷऔΓ૊Έ private let fixtures: [Fixture] = [ .cart(.normal), .promotedDeliveryProducts(.ordinary), .me(.userLocation),

    .feature(.popularProducts), // ུ ] environment.registerClientResponses(fixtures, overrideFixtures: [ .orders(.empty), .userOrderedDeliveries(.empty), ]) • ը໘දࣔʹඞཁͳϨεϙϯεελϒΛFixtureԽ • ϕʔεͷFixtureͱɺ৚݅͝ͱͷoverrideFixturesΛ༻ҙ • ϛχΞϓϦͷ৚݅͝ͱͷը໘දࣔΛ؆୯ʹఆٛͰ͖ΔΑ͏ʹ
  56. ྑ͍ઃܭ΁ͷҙࣝΛνʔϜ΁ਁಁ͢ΔͨΊʹ • ಡΈ΍ͯ͘͢อक͠΍͍͢ઃܭʹ͍ͭͯߟ͑ͨࣄ ◦ ౷Ұͨ͠ॻ͖ํͰϨΠΞ΢τΛઃܭ͢ΔͨΊʹ ◦ ෳࡶɾଟ༷ͳ৚݅ʹରॲ͢Δ ◦ ྑ͍ઃܭ΁ͷҙࣝΛνʔϜ΁ਁಁ͢ΔͨΊʹ

  57. ྑ͍ઃܭ΁ͷҙࣝΛνʔϜ΁ਁಁ͢ΔͨΊʹ • υΩϡϝϯτԽ • υΩϡϝϯτ੔උձ • ஌ݟ·ͱΊࣾ಺ϒϩά • SwiftUIϨΠΞ΢τʹؔ͢Δௐࠪ •

    ઃܭʹ͍ͭͯޠΔձ
  58. ྑ͍ઃܭ΁ͷҙࣝΛνʔϜ΁ਁಁ͢ΔͨΊʹ

  59. ྑ͍ઃܭ΁ͷҙࣝΛνʔϜ΁ਁಁ͢ΔͨΊʹ

  60. ྑ͍ઃܭ΁ͷҙࣝΛνʔϜ΁ਁಁ͢ΔͨΊʹ

  61. ྑ͍ઃܭ΁ͷҙࣝΛνʔϜ΁ਁಁ͢ΔͨΊʹ

  62. ྑ͍ઃܭ΁ͷҙࣝΛνʔϜ΁ਁಁ͢ΔͨΊʹ

  63. ·ͱΊ • ౷Ұͨ͠ॻ͖ํͰϨΠΞ΢τΛઃܭ͢ΔͨΊʹ • ϨΠΞ΢τઃܭΛ౷ҰԽ • ίϯϙʔωϯτԽͷཻ౓Λ໌֬ʹ • ෳࡶɾଟ༷ͳ৚݅ʹରॲ͢Δ •

    ը໘ϨΠΞ΢τͷઃܭਤͱͯ͠RootViewͷbodyΛར༻ • ಈ࡞֬ೝͷͨΊʹϛχΞϓϦΛ׆༻ • ྑ͍ઃܭ΁ͷҙࣝΛνʔϜ΁ਁಁ͢ΔͨΊʹ • ఆظతʹઃܭʹ͍ͭͯٞ࿦͢Δ৔Λઃ͚Δ • υΩϡϝϯτԽ͢Δ͜ͱʹΑͬͯڞ௨ೝࣝΛऔΔ