Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

ࠤ౻ ರ໵ (͋ͭ΍) @n_atmark • iOS / Android ΤϯδχΞ • ݱࡏ͸ΫοΫύουAndroidΞϓϦͷʮ͔͍΋ͷʯλϒΛӶҙ։ൃத 2019/04 2021/01 • ΫοΫύου৽ଔೖࣾ • ങ෺ࣄۀຊ෦ ങ෺ϓϩμΫτ։ൃ෦ • ΫοΫύουϚʔτͷྲྀ௨޲͚ͷαʔϏε։ൃɺϋʔυ΢ΣΞ։ൃͳͲʹैࣄ • ΫοΫύουࣄۀຊ෦ ങ෺αʔϏε։ൃ෦ • ΫοΫύουiOSΞϓϦͷʮ͔͍΋ͷʯλϒͷ։ൃʹैࣄ

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

νʔϜͱ։ൃ͍ͯ͠ΔϓϩμΫτʹ͍ͭͯ ● ങ෺αʔϏε։ൃ෦ ● ʮϨγϐʯ×ʮങ͍෺ʯʹΑͬͯ৽ͨͳՁ஋ΛੜΈ ग़͢௅ઓ ● ΫοΫύουiOSΞϓϦͷʮങ͍෺ػೳʯ ● ΤϯδχΞ6ਓ (iOS 3ɺαʔόʔαΠυ3) ● + ඇఆظͰΠϯλʔϯੜ͕νʔϜʹδϣΠϯ

Slide 11

Slide 11 text

ΫοΫύουΞϓϦʮങ͍෺ػೳʯͷ։ൃ ● ϚϧνϞδϡʔϧԽ͞Ε͍ͯΔΫοΫύουΞϓϦͷ Feature ModuleͷҰͭͱͯ͠ػೳ։ൃ 
 (KaimonoϞδϡʔϧ)

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

ΫοΫύουΞϓϦʮങ͍෺ػೳʯͷ։ൃ ● Kaimono Ϟδϡʔϧ഑Լͷίʔυߦ਺ ● 45,953ߦ (ΫοΫύουiOSશମͷ໿15%) ● UIHostingViewControllerͰϥοϓ͞ΕͨRootView ● 35ը໘ ● ผϑΝΠϧʹ੾Γग़͞ΕͨSwiftUIίϯϙʔωϯτ ● 149ݸ

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

ΞϓϦΛϦϦʔε͔ͯ͠Β1೥։ൃ͍ͯ͘͠தͰͷมԽ ● ίʔυϕʔεͷڊେԽ ● Feature ModuleͷதͰ͸ίʔυߦ਺΋VIPERγʔϯ਺΋࠷େʹ ● iOS 14ɾiOS 15ͷϦϦʔε ● iOS 13ɺ14ɺ15ͷ3όʔδϣϯαϙʔτʹ ● νʔϜͷ֦େ ● ϝΠϯͰ։ൃ͢ΔΤϯδχΞ΋૿͑ͨ ● Πϯλʔϯੜ΋ܞΘΔΑ͏ʹ

Slide 24

Slide 24 text

1೥։ൃͯ͠Έͯײ͍ͯ͡Δ՝୊ ● iOS 13ରԠʹΑΔফ໣͸গͳ͔Βͣൃੜ͢Δ ● iOS 13͚ͩڍಈ͕ҧ͏෦෼͕গͳ͔Βͣ͋Δ ● ύϑΥʔϚϯεΛ٘ਜ਼ʹ͍ͯ͠ΔՕॴ΋݁ߏ͋Δ ● LazyV/HStackɺLazyV/HGrid͸࢖͑ͯͳ͍😢

Slide 25

Slide 25 text

1೥։ൃͯ͠Έͯײ͍ͯ͡Δ՝୊ ● ॊೈੑ͕ߴ͍ͨΊɺUIͷ૊Έํ͕ਓʹΑͬͯมΘΔ ● ྫ: ཁૉΛॏͶ͍ͨͱ͖ͷZStackɺbackgroundɺ overlayͷ࢖͍෼͚ ● ྫ: εϖʔεͷ։͚ํ ● ίϯϙʔωϯτ෼ׂͷཻ౓

Slide 26

Slide 26 text

Q: ࠓޙ΋SwiftUIΛऔΓೖΕͨ։ൃ Λ͢Δʁ ৭ʑফ໣΋ ײͯͦ͡͏͚ͩͲ…?

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

ϨΠΞ΢τ૊Έʹؔͯ͠ struct KaimonoCartView: View { var body: some View { ScrollView { orderDeliverySection cartPriceSection pickupNameSettingSection deliveryInformationSection pickupStepsSection } } }

Slide 39

Slide 39 text

ϨΠΞ΢τ૊Έʹؔͯ͠ ● ը໘Λҙຯͷ͋Δ·ͱ·ΓͰSectionʹ෼ׂ ● ෳ਺ίϯϙʔωϯτΛͱΓ·ͱΊΔ ● ίϯϙʔωϯτؒͷϚʔδϯௐ੔Λ 
 ߦ͏ͨΊͷϨΠϠʔ

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

No content

Slide 43

Slide 43 text

Atoms Molecules Moleculesͷू߹ମ Organisms ProductTile ProductsGrid PopularProductsSection

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

ίϯϙʔωϯτʹؔͯ͠ ● ίϯϙʔωϯτͷཻ౓ʹؔͯ͠νʔϜ಺Ͱೝ͕ࣝऔΕ͍ͯΔͱί ϛϡχέʔγϣϯ͕ͱΓ΍͍͢ ● Sectionͱͯ͠RootViewʹඥͮ͘ܗͰ༻ҙ͢΂͖΋ͷ ● ίϯϙʔωϯτͱͯ͠੾Γग़͢΂͖΋ͷ ● ίϯϙʔωϯτͱͯ͠੾Γग़͢৔߹ ● Ͳ͜·Ͱࡉ͔͘෼ׂ͢Δͷ͔

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

ෳࡶɾଟ༷ͳ৚݅ʹରॲ͢Δ 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: // ུ } } } }

Slide 49

Slide 49 text

ෳࡶɾଟ༷ͳ৚݅ʹରॲ͢Δ ● RootViewͷbodyʹSectionΛྻڍ͢ΔΑ͏ʹͨ͜͠ͱͰ ݟ௨͕͠ྑ͍ ● ঢ়ଶʹԠͨ͡Sectionͷग़͠෼͚΍ɺಛఆ৚݅ʹԠ͡ ͨSectionͷτϧπϝ΋෼͔Γ΍͍͢ ● body͕ը໘ϨΠΞ΢τͷઃܭਤͱͯ͠ػೳ͢Δ

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

ਖ਼֬ʹಈ࡞ͤ͞ΔͨΊͷऔΓ૊Έ 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), // ུ ]

Slide 55

Slide 55 text

ਖ਼֬ʹಈ࡞ͤ͞ΔͨΊͷऔΓ૊Έ private let fixtures: [Fixture] = [ .cart(.normal), .promotedDeliveryProducts(.ordinary), .me(.userLocation), .feature(.popularProducts), // ུ ] environment.registerClientResponses(fixtures, overrideFixtures: [ .orders(.empty), .userOrderedDeliveries(.empty), ]) ● ը໘දࣔʹඞཁͳϨεϙϯεελϒΛFixtureԽ ● ϕʔεͷFixtureͱɺ৚݅͝ͱͷoverrideFixturesΛ༻ҙ ● ϛχΞϓϦͷ৚݅͝ͱͷը໘දࣔΛ؆୯ʹఆٛͰ͖ΔΑ͏ʹ

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

·ͱΊ ● ౷Ұͨ͠ॻ͖ํͰϨΠΞ΢τΛઃܭ͢ΔͨΊʹ ● ϨΠΞ΢τઃܭΛ౷ҰԽ ● ίϯϙʔωϯτԽͷཻ౓Λ໌֬ʹ ● ෳࡶɾଟ༷ͳ৚݅ʹରॲ͢Δ ● ը໘ϨΠΞ΢τͷઃܭਤͱͯ͠RootViewͷbodyΛར༻ ● ಈ࡞֬ೝͷͨΊʹϛχΞϓϦΛ׆༻ ● ྑ͍ઃܭ΁ͷҙࣝΛνʔϜ΁ਁಁ͢ΔͨΊʹ ● ఆظతʹઃܭʹ͍ͭͯٞ࿦͢Δ৔Λઃ͚Δ ● υΩϡϝϯτԽ͢Δ͜ͱʹΑͬͯڞ௨ೝࣝΛऔΔ