Slide 1

Slide 1 text

SwiftUI Navigation ͷ͢΂ͯ iOSDC Japan 2022 kalupas226

Slide 2

Slide 2 text

ࣗݾ঺հ • ΞΠΧϫ • @kalupas226 • Cookpad Inc. iOS Developer 2

Slide 3

Slide 3 text

ΞδΣϯμ • SwiftUI Navigation ͷ၆ᛌ • ༷ʑͳछྨ ͷ Navigation • OS ʹΑΔมԽ͕ܹ͍͠ Navigation • Fire and forget / State driven Navigation API • SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ • Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ • ʮswiftui-navigationʯͷΞϓϩʔν • ·ͱΊ 3

Slide 4

Slide 4 text

􀁟 ຊτʔΫͰ࿩͞ͳ͍͜ͱ • ։ൃऀ͕ͦΕͧΕͰఆٛ͢Δಠࣗͷ Custom Navigation • iOS Ҏ֎ͷϓϥοτϑΥʔϜʹ͓͚Δ Navigation • ΞϓϦέʔγϣϯʹ͓͚Δ Navigation ͸͜͏͋Δ΂͖ͱ͍͏Α͏ͳ 
 σβΠϯతͳ࿩ 4

Slide 5

Slide 5 text

􀁟 ຊτʔΫͰओʹࢀߟʹ͍ͯ͠Δ৘ใ • Point-Free ੡ͷʮswiftui-navigationʯͱ͍͏ϥΠϒϥϦ • https://github.com/pointfreeco/swiftui-navigation • ൃද಺Ͱ͸ҎԼͷΑ͏ʹ۠ผͯ͠આ໌͠·͢ • SwiftUI Navigation API: Apple ७ਖ਼ͷ API ʹ͍ͭͯͷ࿩ • ʮswiftui-navigationʯ: ϥΠϒϥϦʹ͍ͭͯͷ࿩ 5

Slide 6

Slide 6 text

SwiftUI Navigation ͷ၆ᛌ

Slide 7

Slide 7 text

SwiftUI Navigation ͷ၆ᛌ ༷ʑͳछྨͷ Navigation

Slide 8

Slide 8 text

༷ʑͳछྨͷ Navigation API ͕ଘࡏ͢Δ • Tab • Alert • Sheet • Full Screen Cover • Con fi rmation Dialog • Popover • Navigation Link… SwiftUI Navigation ͷ၆ᛌ > ༷ʑͳछྨͷ Navigation 8

Slide 9

Slide 9 text

Tab TabView { FirstView() .tabItem { Image(systemName: "exclamationmark.circle") Text("Alert") } SecondView() .tabItem {…} ThirdView() .tabItem {…} FourthView() .tabItem {…} } SwiftUI Navigation ͷ၆ᛌ > ༷ʑͳछྨͷ Navigation

Slide 10

Slide 10 text

Alert BaseView() .alert( “Alert͕දࣔ͞Ε·ͨ͠”, isPresented: $isPresentedAlert, actions: { Button("OK", action: {}) } ) SwiftUI Navigation ͷ၆ᛌ > ༷ʑͳछྨͷ Navigation

Slide 11

Slide 11 text

Sheet BaseView() .sheet( isPresented: $isPresentedAlert, content: { Text("Sheet͕දࣔ͞Ε·ͨ͠") } ) SwiftUI Navigation ͷ၆ᛌ > ༷ʑͳछྨͷ Navigation

Slide 12

Slide 12 text

NavigationViewɾNavigationLink (Deprecated) NavigationView { ForEach(1...10, id: \.self) { id in NavigationLink( "Go to \(id) simple destination", destination: { Text("This is \(id) destination") } ) } } SwiftUI Navigation ͷ၆ᛌ > ༷ʑͳछྨͷ Navigation

Slide 13

Slide 13 text

SwiftUI Navigation ͷ၆ᛌ OS ʹΑΔมԽ͕ܹ͍͠ Navigation

Slide 14

Slide 14 text

OS ͕ਐԽ͢ΔʹͭΕ API ͷܗ΋มΘ͖ͬͯͨ • ActionSheet API (deprecated) → Con fi rmation Dialog API • Alert API • deprecated ʹͳͬͨ΋ͷͱɺͦ͏Ͱͳ͍΋ͷ͕͋Δ • Navigation-base API • NavigationView → NavigationStack • NavigationLink 14 SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation

Slide 15

Slide 15 text

ActionSheet API (deprecated) .actionSheet(isPresented: $showActionSheet) { ActionSheet( title: Text(...), message: Text(...), buttons: [ .cancel(), .destructive( Text(...), action: {} ), .default( Text(...), action: {} ) ] ) } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation

Slide 16

Slide 16 text

ActionSheet API (deprecated) .actionSheet(isPresented: $showActionSheet) { ActionSheet( title: Text(...), message: Text(...), buttons: [ .cancel(), .destructive( Text(...), action: {} ), .default( Text(...), action: {} ) ] ) } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation

Slide 17

Slide 17 text

ActionSheet API (deprecated) .actionSheet(isPresented: $showActionSheet) { ActionSheet( title: Text(...), message: Text(...), buttons: [ .cancel(), .destructive( Text(...), action: {} ), .default( Text(...), action: {} ) ] ) } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation

Slide 18

Slide 18 text

Con fi rmation Dialog API(iOS 15~) .confirmationDialog( “Title", isPresented: $isConfirming presenting: dialogDetail ) { detail in Button { } label: { Text("Import \(detail.name)") } Button("Cancel", role: .cancel) { dialogDetail = nil } } message: { detail in Text(\(detail.name) \(detail.type)) } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation

Slide 19

Slide 19 text

Con fi rmation Dialog API(iOS 15~) .confirmationDialog( “Title", isPresented: $isConfirming, presenting: dialogDetail ) { detail in Button { } label: { Text("Import \(detail.name)") } Button("Cancel", role: .cancel) { dialogDetail = nil } } message: { detail in Text(\(detail.name) \(detail.type)) } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation

Slide 20

Slide 20 text

Con fi rmation Dialog API(iOS 15~) .confirmationDialog( “Title", isPresented: $isConfirming, presenting: dialogDetail ) { detail in Button { } label: { Text("Import \(detail.name)") } Button("Cancel", role: .cancel) { dialogDetail = nil } } message: { detail in Text(\(detail.name) \(detail.type)) } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation

Slide 21

Slide 21 text

Alert API (deprecated) .alert(isPresented: $showAlert) { Alert( title: Text("Title"), message: Text("Message") ) } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation

Slide 22

Slide 22 text

Alert API (deprecated) .alert(item: $alertDetails) { details in Alert( title: Text("Title"), message: Text(""" Imported \(details.name) \n Filetype: \(details.fileType). """), dismissButton: .default(Text("Dismiss")) ) } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation

Slide 23

Slide 23 text

Alert API (iOS 15~) .alert( "Alert͕දࣔ͞Ε·ͨ͠", isPresented: $isPresentedAlert, actions: { Button("OK", action: {}) } ) SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation

Slide 24

Slide 24 text

NavigationViewɾOld NavigationLink (deprecated) NavigationView { List(model.notes) { note in NavigationLink( note.title, destination: NoteEditor(id: note.id) ) } } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation

Slide 25

Slide 25 text

NavigationViewɾOld NavigationLink (deprecated) NavigationView { List(model.notes) { note in NavigationLink( note.title, destination: NoteEditor(id: note.id) ) } } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation

Slide 26

Slide 26 text

NavigationViewɾOld NavigationLink (deprecated) NavigationView { List(model.notes) { note in NavigationLink( note.title, // ભҠݩͷ View ʹදࣔ͞ΕΔ title destination: NoteEditor(id: note.id) // ભҠޙͷը໘ ) } } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation

Slide 27

Slide 27 text

Simple NavigationStackɾNew NavigationLink NavigationStack { List(parks) { park in NavigationLink( park.name, value: park ) } .navigationDestination(for: Park.self) { park in ParkDetails(park: park) } } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation

Slide 28

Slide 28 text

Simple NavigationStackɾNew NavigationLink NavigationStack { List(parks) { park in NavigationLink( park.name, value: park ) } .navigationDestination(for: Park.self) { park in ParkDetails(park: park) } } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation

Slide 29

Slide 29 text

Simple NavigationStackɾNew NavigationLink NavigationStack { List(parks) { park in NavigationLink( park.name, // ભҠݩͷը໘ʹදࣔ͢Δ title value: park // ೚ҙͷܕͷ value ) } .navigationDestination(for: Park.self) { park in ParkDetails(park: park) } } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation

Slide 30

Slide 30 text

Simple NavigationStackɾNew NavigationLink NavigationStack { List(parks) { park in NavigationLink( park.name, value: park ) } // value ͷܕʹԠͯ͡ navigationDestination ͕൓Ԡ͢Δ .navigationDestination(for: Park.self) { park in ParkDetails(park: park) } } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation

Slide 31

Slide 31 text

Binding NavigationStackɾNew NavigationLink @State private var presentedParks: [Park] = [] // ... NavigationStack(path: $presentedParks) { List(parks) { park in NavigationLink(park.name, value: park) } .navigationDestination(for: Park.self) { park in ParkDetails(park: park) } } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation

Slide 32

Slide 32 text

Binding NavigationStackɾNew NavigationLink @State private var presentedParks: [Park] = [] // ... NavigationStack(path: $presentedParks) { List(parks) { park in NavigationLink(park.name, value: park) } .navigationDestination(for: Park.self) { park in ParkDetails(park: park) } } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation

Slide 33

Slide 33 text

Binding NavigationStackɾNew NavigationLink @State private var presentedParks: [Park] = [] // ... NavigationStack(path: $presentedParks) { // ... } func showParks() { // RootView -> Park("Yosemite") -> Park("Sequoia") presentedParks = [Park("Yosemite"), Park("Sequoia")] } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation ※ iOS 16 ͷ API ʹ͍ͭͯͷ FB: https://gist.github.com/mbrandonw/f8b94957031160336cac6898a919cbb7

Slide 34

Slide 34 text

SwiftUI Navigation ͷ၆ᛌ Fire and forget / State driven Navigation API

Slide 35

Slide 35 text

Navigation API ͸େ͖͘ 2 ͭʹ෼ྨͰ͖Δ • ʮswiftui-navigationʯREADME ͔ΒҾ༻ • Fire and forget Navigation API • State driven Navigation API 35 SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API

Slide 36

Slide 36 text

Navigation API ͸େ͖͘ 2 ͭʹ෼ྨͰ͖Δ • Fire and forget Navigation API • State driven Navigation API 36 SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API

Slide 37

Slide 37 text

Fire and forget Navigation API • Binding Ҿ਺ΛऔΒͳ͍ • SwiftUI ͕ Navigation ͷঢ়ଶΛ׬શʹ಺෦Ͱ؅ཧ͢Δ • Navigation Λૉૣ࣮͘ݱͰ͖Δ͕ɺNavigation ʹରͯ͠ 
 ϓϩάϥϜతͳ੍ޚ͕Ͱ͖ͳ͘ͳΔ 37 SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API

Slide 38

Slide 38 text

Fire and forget API - Tab - TabView { ReceivedView() .tabItem { // ... } SentView() .tabItem { // ... } AccountView() .tabItem { // ... } } SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API

Slide 39

Slide 39 text

Fire and forget API - Tab - // Binding Ҿ਺ΛऔΒͳ͍ɻλοϓͰ͔͠ navigation Ͱ͖ͳ͍ TabView { ReceivedView() .tabItem { // ... } SentView() .tabItem { // ... } AccountView() .tabItem { // ... } } SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API

Slide 40

Slide 40 text

Fire and forget API - NavigationLink - NavigationView { List(model.notes) { note in NavigationLink( note.title, destination: NoteEditor(id: note.id) ) } Text("Select a Note") } SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API

Slide 41

Slide 41 text

Fire and forget API - NavigationLink - NavigationView { List(model.notes) { note in // Binding Ҿ਺ΛऔΒͳ͍ɻλοϓͰ͔͠ navigation Ͱ͖ͳ͍ NavigationLink( note.title, destination: NoteEditor(id: note.id) ) } Text("Select a Note") } SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API

Slide 42

Slide 42 text

Navigation API ͸େ͖͘ 2 ͭʹ෼ྨͰ͖Δ • Fire and forget Navigation API • State driven Navigation API 42 SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API

Slide 43

Slide 43 text

State driven Navigation API • Binding Ҿ਺ΛऔΔ • Navigation Λ༗ޮɾແޮʹ͢Δ࣌ʹυϝΠϯͷঢ়ଶ΋มߋͰ͖Δ • Fire and forget API ΑΓෳࡶͰ͸͋Δ͕ɺϓϩάϥϜతͳ੍ޚ͕ 
 ՄೳͱͳΔͨΊɺ࢖͍ํʹΑͬͯ͸ Deep Link ͳͲ΋࣮ݱͰ͖Δ 43 SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API

Slide 44

Slide 44 text

State driven API - Tab - struct ContentView: View { @State var selectedTab: Tab = .received var body: some View { TabView(selection: $selectedTab) { ReceivedView().tabItem { ... } .tag(Tab.received) SentView().tabItem { ... } .tag(Tab.sent) AccountView().tabItem { ... } .tag(Tab.account) } } } SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API

Slide 45

Slide 45 text

State driven API - Tab - struct ContentView: View { @State var selectedTab: Tab = .received var body: some View { TabView(selection: $selectedTab) { ReceivedView().tabItem { ... } .tag(Tab.received) SentView().tabItem { ... } .tag(Tab.sent) AccountView().tabItem { ... } .tag(Tab.account) } } } SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API

Slide 46

Slide 46 text

State driven API - Tab - struct ContentView: View { @State var selectedTab: Tab = .sent var body: some View { TabView(selection: $selectedTab) { ReceivedView().tabItem { ... } .tag(Tab.received) SentView().tabItem { ... } .tag(Tab.sent) AccountView().tabItem { ... } .tag(Tab.account) } } } SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API

Slide 47

Slide 47 text

ҟͳΔ View ͰแΉͱ Deep Link Ͱ͖ͳ͍ struct ContainerView: View { var body: some View { ContentView(selectedTab: .received) } } SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API

Slide 48

Slide 48 text

ContainerView ʹঢ়ଶΛ࣋ͨͤͯղܾ͢Δʁ struct ContainerView: View { let selectedTab: Tab var body: some View { ContentView(selectedTab: selectedTab) } } SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API

Slide 49

Slide 49 text

ContainerView ʹঢ়ଶΛ࣋ͨͤͯղܾ͢Δʁ struct ContainerView: View { // ContainerView ʹؔ܎ͳ͍ Tab ͷঢ়ଶΛ࣋ͨͤΔͷ͸ඍົ // ͔͠΋ ContentView ͷ selectedTab ͸ @State ͳͷͰޡΓ let selectedTab: Tab var body: some View { ContentView(selectedTab: selectedTab) } } SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API

Slide 50

Slide 50 text

ΞϓϦͷঢ়ଶΛ؅ཧ͢Δ ViewModel Λಋೖ͠ 
 ղܾ͢Δ class AppViewModel: ObservableObject { @Published var selectedTab: Tab init(selectedTab: Tab = .received) { self.selectedTab = selectedTab } } SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API

Slide 51

Slide 51 text

ΞϓϦͷঢ়ଶΛ؅ཧ͢Δ ViewModel Λಋೖ͠ 
 ղܾ͢Δ struct ContentView: View { @ObservedObject var viewModel: AppViewModel var body: some View { TabView(selection: $viewModel.selectedTab) { // ... } } } // ContentView ͷ initialize ࣌ʹ Tab Λૢ࡞Ͱ͖ΔΑ͏ʹͳͬͨ ContentView(viewModel: .init(selectedTab: .two)) SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API

Slide 52

Slide 52 text

SwiftUI ͷ Navigation API 
 ʹ͓͚Δ՝୊

Slide 53

Slide 53 text

Navigation API ʹ͓͚Δ՝୊ 1. ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ 2. ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ 3. ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊

Slide 54

Slide 54 text

Navigation API ʹ͓͚Δ՝୊ 1. ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ 2. ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ 3. ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍

Slide 55

Slide 55 text

ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛ උ͍͑ͯͳ͍ struct ContentView: View { @State var draft: Post? var body: some View { Button("Edit") { draft = Post() } .sheet(item: $draft) { (draft: Post) in EditPostView(post: draft) } } } struct EditPostView: View { let post: Post var body: some View { ... } } SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍

Slide 56

Slide 56 text

ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛ උ͍͑ͯͳ͍ struct ContentView: View { @State var draft: Post? var body: some View { Button("Edit") { draft = Post() } .sheet(item: $draft) { (draft: Post) in EditPostView(post: draft) } } } struct EditPostView: View { let post: Post var body: some View { ... } } SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍

Slide 57

Slide 57 text

ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛ උ͍͑ͯͳ͍ struct ContentView: View { @State var draft: Post? var body: some View { Button("Edit") { draft = Post() } .sheet(item: $draft) { (draft: Post) in EditPostView(post: draft) } } } struct EditPostView: View { let post: Post var body: some View { ... } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ Binding ValueΛ EditPostViewʹ
 ౉ͤͳ͍ EditPostViewͰͷ มߋ͕ContentView ʹ൓ө͞Εͳ͍

Slide 58

Slide 58 text

Navigation API ʹ͓͚Δ՝୊ 1. ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ 2. ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ 3. ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ

Slide 59

Slide 59 text

Deprecated / New Alert API // Deprecated API // Binding Λड͚औΔ func alert( isPresented: Binding, content: () -> Alert ) -> some View // Binding Λड͚औΔ func alert( item: Binding, content: (Item) -> Alert ) -> some View where Item : Identifiable // New API // Binding Λड͚औΔ func alert( _ title: Text, isPresented: Binding, actions: () -> A ) -> some View where A : View // Binding ͱ data Λड͚औΔ func alert( _ title: Text, isPresented: Binding, presenting data: T?, actions: (T) -> A ) -> some View where A : View SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ

Slide 60

Slide 60 text

Deprecated / New Alert API // Deprecated API // Binding Λड͚औΔ func alert( isPresented: Binding, content: () -> Alert ) -> some View // Binding Λड͚औΔ func alert( item: Binding, content: (Item) -> Alert ) -> some View where Item : Identifiable // New API // Binding Λड͚औΔ func alert( _ title: Text, isPresented: Binding, actions: () -> A ) -> some View where A : View // Binding ͱ data Λड͚औΔ func alert( _ title: Text, isPresented: Binding, presenting data: T?, actions: (T) -> A ) -> some View where A : View SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ

Slide 61

Slide 61 text

Deprecated boolean binding API struct ExampleView: View { @State private var showAlert = false var body: some View { BaseView(...) .alert(isPresented: $showAlert) { Alert(...) } } } SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ

Slide 62

Slide 62 text

Deprecated / New Alert API // Deprecated API // Binding Λड͚औΔ func alert( isPresented: Binding, content: () -> Alert ) -> some View // Binding Λड͚औΔ func alert( item: Binding, content: (Item) -> Alert ) -> some View where Item : Identifiable // New API // Binding Λड͚औΔ func alert( _ title: Text, isPresented: Binding, actions: () -> A ) -> some View where A : View // Binding ͱ data Λड͚औΔ func alert( _ title: Text, isPresented: Binding, presenting data: T?, actions: (T) -> A ) -> some View where A : View SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ

Slide 63

Slide 63 text

Deprecated optional item binding API struct ExampleView: View { @State private var item: Item? var body: some View { BaseView(...) .alert(item: $item) { item in Alert(...) // item Λར༻ͯ͠ alert ΛΧελϚΠζͰ͖Δ } } } SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ

Slide 64

Slide 64 text

Deprecated / New Alert API // Deprecated API // Binding Λड͚औΔ func alert( isPresented: Binding, content: () -> Alert ) -> some View // Binding Λड͚औΔ func alert( item: Binding, content: (Item) -> Alert ) -> some View where Item : Identifiable // New API // Binding Λड͚औΔ func alert( _ title: Text, isPresented: Binding, actions: () -> A ) -> some View where A : View // Binding ͱ data Λड͚औΔ func alert( _ title: Text, isPresented: Binding, presenting data: T?, actions: (T) -> A ) -> some View where A : View SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ

Slide 65

Slide 65 text

New boolean binding API struct ExampleView: View { @State private var showAlert = false var body: some View { BaseView(...) .alert( "Alert title", isPresented: $showAlert, action: { ... } ) } } SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ

Slide 66

Slide 66 text

Deprecated / New Alert API // Deprecated API // Binding Λड͚औΔ func alert( isPresented: Binding, content: () -> Alert ) -> some View // Binding Λड͚औΔ func alert( item: Binding, content: (Item) -> Alert ) -> some View where Item : Identifiable // New API // Binding Λड͚औΔ func alert( _ title: Text, isPresented: Binding, actions: () -> A ) -> some View where A : View // Binding ͱ data Λड͚औΔ func alert( _ title: Text, isPresented: Binding, presenting data: T?, actions: (T) -> A ) -> some View where A : View SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ

Slide 67

Slide 67 text

New boolean binding and optional item API struct ExampleView: View { @State private var showAlert = false @State private var item: Item? var body: some View { BaseView(...) .alert( "Alert title", isPresented: $showAlert, presenting: item action: { item in ... }, message: { item in ... } ) } } SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ

Slide 68

Slide 68 text

New boolean binding and optional item API struct ExampleView: View { @State private var showAlert = false @State private var item: Item? var body: some View { BaseView(...) .alert( "Alert title", isPresented: $showAlert, presenting: item action: { item in ... }, message: { item in ... } ) } } SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ 􀁣 showAlert: true item: non null

Slide 69

Slide 69 text

New boolean binding and optional item API struct ExampleView: View { @State private var showAlert = false @State private var item: Item? var body: some View { BaseView(...) .alert( "Alert title", isPresented: $showAlert, presenting: item action: { item in ... }, message: { item in ... } ) } } SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ 􀁡 showAlert: true item: null

Slide 70

Slide 70 text

New boolean binding and optional item API ͸ 
 ঢ়ଶ؅ཧΛෳࡶʹͤͯ͞͠·͏ • ։ൃऀ͕ҎԼͷঢ়ଶͷ੔߹ੑΛؾʹ͠ͳ͚Ε͹͍͚ͳ͍ͷ͕ਏ͍ • Alert Λදࣔ͢ΔͨΊͷ boolean binding • Alert ͷ಺༰Λ࡞ΔͨΊͷ optional item • Navigation ͕γϯϓϧͳ͏ͪ͸ͦ͜·ͰࠔΒͳ͍͔΋͠Εͳ͍͕ɺ 
 Navigation ͕૿͑Ε͹༰қʹঢ়ଶ؅ཧ΋ෳࡶʹͳͬͯ͠·͏ SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ

Slide 71

Slide 71 text

Navigation API ʹ͓͚Δ՝୊ 1. ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ 2. ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ 3. ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ

Slide 72

Slide 72 text

ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱ 
 ແବͳঢ়ଶ͕૿͑Δ struct ContentView: View { @State var draft: Post? @State var settings: Settings? @State var userProfile: Profile? var body: some View { BaseView(...) .sheet(item: self.$draft) { (draft: Post) in EditPostView(post: draft) } .sheet(item: self.$settings) { (settings: Settings) in SettingsView(settings: settings) } .sheet(item: self.$userProfile) { (userProfile: Profile) in UserProfile(profile: userProfile) } } } SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ

Slide 73

Slide 73 text

ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱ 
 ແବͳঢ়ଶ͕૿͑Δ struct ContentView: View { @State var draft: Post? @State var settings: Settings? @State var userProfile: Profile? var body: some View { BaseView(...) .sheet(item: self.$draft) { (draft: Post) in EditPostView(post: draft) } .sheet(item: self.$settings) { (settings: Settings) in SettingsView(settings: settings) } .sheet(item: self.$userProfile) { (userProfile: Profile) in UserProfile(profile: userProfile) } } } SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ

Slide 74

Slide 74 text

ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱ 
 ແବͳঢ়ଶ͕૿͑Δ struct ContentView: View { @State var draft: Post? // null + non null = 2 @State var settings: Settings? // null + non null = 2 @State var userProfile: Profile? // null + non null = 2 var body: some View { BaseView(...) .sheet(item: self.$draft) { (draft: Post) in EditPostView(post: draft) } .sheet(item: self.$settings) { (settings: Settings) in SettingsView(settings: settings) } .sheet(item: self.$userProfile) { (userProfile: Profile) in UserProfile(profile: userProfile) } } } SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ

Slide 75

Slide 75 text

༷ʑͳύλʔϯͷঢ়ଶ͕ൃੜͯ͠͠·͏ %SBGU 4FUUJOHT 1SP fi MF ύλʔϯ /VMM /VMM /VMM ύλʔϯ /POOVMM /VMM /VMM ύλʔϯ /VMM /POOVMM /VMM ύλʔϯ /VMM /VMM /POOVMM ύλʔϯ /POOVMM /POOVMM /VMM ύλʔϯ /POOVMM /VMM /POOVMM ύλʔϯ /VMM /POOVMM /POOVMM ύλʔϯ /POOVMM /POOVMM /POOVMM SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ

Slide 76

Slide 76 text

༷ʑͳύλʔϯͷঢ়ଶ͕ൃੜͯ͠͠·͏ %SBGU 4FUUJOHT 1SP fi MF ύλʔϯ /VMM /VMM /VMM ύλʔϯ /POOVMM /VMM /VMM ύλʔϯ /VMM /POOVMM /VMM ύλʔϯ /VMM /VMM /POOVMM ύλʔϯ /POOVMM /POOVMM /VMM ύλʔϯ /POOVMM /VMM /POOVMM ύλʔϯ /VMM /POOVMM /POOVMM ύλʔϯ /POOVMM /POOVMM /POOVMM ༗ޮͳঢ়ଶ͸͜ΕΒͷΈ SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ

Slide 77

Slide 77 text

Navigation API ͷ՝୊ʹ 
 Ͳ͏ཱͪ޲͔͏͔

Slide 78

Slide 78 text

Navigation API ʹ͓͚Δ՝୊ 1. ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ 2. ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ 3. ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔

Slide 79

Slide 79 text

ʮswiftui-navigation ʯͷΞϓϩʔν 1. ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ • Binding value Λ౉͢͜ͱ͕Ͱ͖Δ API overloads 2. ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ • ࠷௿ݶͷঢ়ଶͷΈΛཁٻ͢Δ API overloads 3. ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ • Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔

Slide 80

Slide 80 text

swiftui-navigation ͱ͸ʁ • SwiftUI ͷ Navigation ʹ focus ͨ͠ Point-Free ੡ͷϥΠϒϥϦ • SwiftUI ͷ Navigation Λར༻͢Δࡍͷ༷ʑͳ՝୊Λղܾ͢ΔͨΊʹҎԼͷ 3 ͭͷπʔϧΛఏڙ͍ͯ͠Δ • Navigation API overloads • ͜ͷޙ࿩͠·͢ • Navigation views ( `IfLet`, `IfCaseLet`, `Switch`/`CaseLet` ) • ໊લͷ௨Γͷ View ܈ɻBinding value Λѻ͑ΔΑ͏ʹઃܭ͞Ε͍ͯΔ • Binding transformations • ಠࣗͷ Navigation Λ࡞Δࡍʹ༗༻ͳπʔϧ Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔

Slide 81

Slide 81 text

ʮswiftui-navigation ʯͷΞϓϩʔν 1. ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ • Binding value Λ౉͢͜ͱ͕Ͱ͖Δ API overloads 2. ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ • ࠷௿ݶͷঢ়ଶͷΈΛཁٻ͢Δ API overloads 3. ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ • Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔

Slide 82

Slide 82 text

ʮswiftui-navigation ʯͷΞϓϩʔν 1. ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ • Binding value Λ౉͢͜ͱ͕Ͱ͖Δ API overloads 2. ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ • ࠷௿ݶͷঢ়ଶͷΈΛཁٻ͢Δ API overloads 3. ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ • Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ > Binding value Λ౉͢͜ͱ͕Ͱ͖Δ API overloads

Slide 83

Slide 83 text

ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛ උ͍͑ͯͳ͍ struct ContentView: View { @State var draft: Post? var body: some View { Button("Edit") { draft = Post() } .sheet(item: $draft) { (draft: Post) in EditPostView(post: draft) } } } struct EditPostView: View { let post: Post var body: some View { ... } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ > Binding value Λ౉͢͜ͱ͕Ͱ͖Δ API overloads

Slide 84

Slide 84 text

ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛ උ͍͑ͯͳ͍ struct ContentView: View { @State var draft: Post? var body: some View { Button("Edit") { draft = Post() } .sheet(item: $draft) { (draft: Post) in EditPostView(post: draft) } } } struct EditPostView: View { let post: Post var body: some View { ... } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ > Binding value Λ౉͢͜ͱ͕Ͱ͖Δ API overloads Binding ValueΛ EditPostViewʹ
 ౉ͤͳ͍ EditPostViewͰͷ มߋ͕ContentView ʹ൓ө͞Εͳ͍

Slide 85

Slide 85 text

Binding Value Λ౉ͤΔ sheet API Λߟ͑Δ struct ContentView: View { @State var draft: Post? var body: some View { Button("Edit") { draft = Post() } .sheet(item: $draft) { (draft: Post) in EditPostView(post: draft) } } } struct EditPostView: View { let post: Post var body: some View { ... } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ > Binding value Λ౉͢͜ͱ͕Ͱ͖Δ API overloads

Slide 86

Slide 86 text

Binding Value Λ౉ͤΔ sheet API Λߟ͑Δ struct ContentView: View { @State var draft: Post? var body: some View { Button("Edit") { draft = Post() } .sheet(item: $draft) { ($draft: Post) in // closure ʹ Binding value Λ౉ͤΔΑ͏ʹͳͬͨΒྑͦ͞͏ EditPostView(post: $draft) } } } struct EditPostView: View { @Binding var post: Post var body: some View { ... } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ > Binding value Λ౉͢͜ͱ͕Ͱ͖Δ API overloads

Slide 87

Slide 87 text

Binding Value Λ౉ͤΔ sheet API Λߟ͑Δ extension View { func sheet( unwrapping optionalValue: Binding, @ViewBuilder content: @escaping (Binding) -> Content ) -> some View where Value: Identifiable, Content: View { self.sheet(item: optionalValue) { _ in // Binding Λ Binding ʹม׵͢Δ value = ??? content(value) } } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ > Binding value Λ౉͢͜ͱ͕Ͱ͖Δ API overloads

Slide 88

Slide 88 text

Binding Value Λ౉ͤΔ sheet API Λߟ͑Δ extension View { func sheet( unwrapping optionalValue: Binding, @ViewBuilder content: @escaping (Binding) -> Content ) -> some View where Value: Identifiable, Content: View { self.sheet(item: optionalValue) { _ in // Binding Λ Binding ʹม׵͢Δ value = ??? content(value) } } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ > Binding value Λ౉͢͜ͱ͕Ͱ͖Δ API overloads

Slide 89

Slide 89 text

Binding Value Λ౉ͤΔ sheet API Λߟ͑Δ extension View { func sheet( unwrapping optionalValue: Binding, @ViewBuilder content: @escaping (Binding) -> Content ) -> some View where Value: Identifiable, Content: View { self.sheet(item: optionalValue) { _ in // Binding Λ Binding ʹม׵͢Δ value = ??? content(value) } } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ > Binding value Λ౉͢͜ͱ͕Ͱ͖Δ API overloads

Slide 90

Slide 90 text

Binding Value Λ౉ͤΔ sheet API Λߟ͑Δ extension View { func sheet( unwrapping optionalValue: Binding, @ViewBuilder content: @escaping (Binding) -> Content ) -> some View where Value: Identifiable, Content: View { self.sheet(item: optionalValue) { _ in // Binding Λ Binding ʹม׵͢Δ value = ??? content(value) } } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ > Binding value Λ౉͢͜ͱ͕Ͱ͖Δ API overloads

Slide 91

Slide 91 text

Binding Λ Binding ʹม׵͢Δ extension Binding { init?(unwrapping binding: Binding) { guard let wrappedValue = binding.wrappedValue else { return nil } self.init( get: { wrappedValue }, set: { binding.wrappedValue = $0 } ) } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ > Binding value Λ౉͢͜ͱ͕Ͱ͖Δ API overloads ※ Binding failable initializer ͸ඪ४Ͱଘࡏ͢Δ͕ɺόά͕͋Δ: https://gist.github.com/stephencelis/3a232a1b718bab0ae1127ebd5fcf6f97

Slide 92

Slide 92 text

Binding Λ Binding ʹม׵͢Δ extension Binding { init?(unwrapping binding: Binding) { guard let wrappedValue = binding.wrappedValue else { return nil } self.init( get: { wrappedValue }, set: { binding.wrappedValue = $0 } ) } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ > Binding value Λ౉͢͜ͱ͕Ͱ͖Δ API overloads

Slide 93

Slide 93 text

Binding Λ Binding ʹม׵͢Δ extension Binding { init?(unwrapping binding: Binding) { guard let wrappedValue = binding.wrappedValue else { return nil } self.init( get: { wrappedValue }, set: { binding.wrappedValue = $0 } ) } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ > Binding value Λ౉͢͜ͱ͕Ͱ͖Δ API overloads

Slide 94

Slide 94 text

Binding Λ Binding ʹม׵͢Δ extension Binding { init?(unwrapping binding: Binding) { guard let wrappedValue = binding.wrappedValue else { return nil } self.init( get: { wrappedValue }, set: { binding.wrappedValue = $0 } ) } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ > Binding value Λ౉͢͜ͱ͕Ͱ͖Δ API overloads

Slide 95

Slide 95 text

࡞੒ͨ͠ init?(unwrapping:) Λద༻͢Δ extension View { func sheet( unwrapping optionalValue: Binding, @ViewBuilder content: @escaping (Binding) -> Content ) -> some View where Value: Identifiable, Content: View { self.sheet(item: optionalValue) { _ in if let value = Binding(unwrapping: optionalValue) { content(value) } } } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ > Binding value Λ౉͢͜ͱ͕Ͱ͖Δ API overloads

Slide 96

Slide 96 text

࡞੒ͨ͠ init?(unwrapping:) Λద༻͢Δ extension View { func sheet( unwrapping optionalValue: Binding, @ViewBuilder content: @escaping (Binding) -> Content ) -> some View where Value: Identifiable, Content: View { self.sheet(item: optionalValue) { _ in if let value = Binding(unwrapping: optionalValue) { content(value) } } } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ > Binding value Λ౉͢͜ͱ͕Ͱ͖Δ API overloads

Slide 97

Slide 97 text

Before / After struct ContentView: View { @State var draft: Post? var body: some View { Button("Edit") { draft = Post() } .sheet(unwrapping: $draft) { $draft in EditPostView(post: $draft) } } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ > Binding value Λ౉͢͜ͱ͕Ͱ͖Δ API overloads struct ContentView: View { @State var draft: Post? var body: some View { Button("Edit") { draft = Post() } .sheet(item: $draft) { draft in EditPostView(post: draft) } } } #FGPSF "GUFS

Slide 98

Slide 98 text

ʮswiftui-navigation ʯͷΞϓϩʔν 1. ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ • Binding value Λ౉͢͜ͱ͕Ͱ͖Δ API overloads 2. ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ • ࠷௿ݶͷঢ়ଶͷΈΛཁٻ͢Δ API overloads 3. ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ • Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ > ࠷௿ݶͷঢ়ଶͷΈΛཁٻ͢Δ API overloads

Slide 99

Slide 99 text

ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ struct ExampleView: View { @State private var showAlert = false @State private var item: Item? var body: some View { BaseView(...) .alert( "Alert title", isPresented: $showAlert, presenting: item action: { item in ... }, message: { item in ... } ) } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ > ࠷௿ݶͷঢ়ଶͷΈΛཁٻ͢Δ API overloads

Slide 100

Slide 100 text

ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ struct ExampleView: View { @State private var showAlert = false @State private var item: Item? var body: some View { BaseView(...) .alert( "Alert title", isPresented: $showAlert, presenting: item action: { item in ... }, message: { item in ... } ) } } 􀁣 showAlert: true item: non null Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ > ࠷௿ݶͷঢ়ଶͷΈΛཁٻ͢Δ API overloads

Slide 101

Slide 101 text

ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ struct ExampleView: View { @State private var showAlert = false @State private var item: Item? var body: some View { BaseView(...) .alert( "Alert title", isPresented: $showAlert, presenting: item action: { item in ... }, message: { item in ... } ) } } 􀁡 showAlert: true item: null Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ > ࠷௿ݶͷঢ়ଶͷΈΛཁٻ͢Δ API overloads

Slide 102

Slide 102 text

ͳͥঢ়ଶ؅ཧΛෳࡶʹ͢Δ API ʹͳ͍ͬͯΔͷ͔ struct ExampleView: View { @State private var showAlert = false @State private var item: Item? var body: some View { BaseView(...) .alert( "Alert title", isPresented: $showAlert, // Alert Λදࣔ͢ΔͨΊͷ Boolean presenting: item // Alert ͷ಺༰ΛΧελϚΠζ͢ΔͨΊͷ optional item action: { item in ... }, message: { item in ... } ) } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞ͳ͍ API overloads

Slide 103

Slide 103 text

ঢ়ଶ؅ཧΛෳࡶʹͤ͞ͳ͍ API ͸ͲΜͳܗ͔ struct ExampleView: View { @State private var showAlert = false @State private var item: Item? var body: some View { BaseView(...) .alert( title: { item in ... }, presenting: item // optional item ͷΈͰʮalert ͷදࣔ৚݅ʯʮalertͷ಺༰ʯΛܾΊΒΕΔ action: { item in ... }, message: { item in ... } ) } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞ͳ͍ API overloads

Slide 104

Slide 104 text

Optional item ͷΈΛཁٻ͢Δ API Λߟ͑Δ extension View { func alert( title: (T) -> Text, presenting data: Binding, @ViewBuilder actions: @escaping (T) -> A, @ViewBuilder message: @escaping (T) -> M ) -> some View { self.alert( ???, // alert title isPresented: ???, presenting: data.wrappedValue, actions: actions, message: message ) } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞ͳ͍ API overloads

Slide 105

Slide 105 text

Optional item ͷΈΛཁٻ͢Δ API Λߟ͑Δ extension View { func alert( title: (T) -> Text, presenting data: Binding, @ViewBuilder actions: @escaping (T) -> A, @ViewBuilder message: @escaping (T) -> M ) -> some View { self.alert( ???, // alert title isPresented: ???, presenting: data.wrappedValue, actions: actions, message: message ) } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞ͳ͍ API overloads

Slide 106

Slide 106 text

Optional item ͷΈΛཁٻ͢Δ API Λߟ͑Δ extension View { func alert( title: (T) -> Text, presenting data: Binding, @ViewBuilder actions: @escaping (T) -> A, @ViewBuilder message: @escaping (T) -> M ) -> some View { self.alert( ???, // alert title isPresented: ???, presenting: data.wrappedValue, actions: actions, message: message ) } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞ͳ͍ API overloads

Slide 107

Slide 107 text

Optional item ͷΈΛཁٻ͢Δ API Λߟ͑Δ extension View { func alert( title: (T) -> Text, presenting data: Binding, @ViewBuilder actions: @escaping (T) -> A, @ViewBuilder message: @escaping (T) -> M ) -> some View { self.alert( data.wrappedValue.map(title) ?? Text(""), isPresented: ???, presenting: data.wrappedValue, actions: actions, message: message ) } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞ͳ͍ API overloads

Slide 108

Slide 108 text

Optional item ͷΈΛཁٻ͢Δ API Λߟ͑Δ extension View { func alert( title: (T) -> Text, presenting data: Binding, @ViewBuilder actions: @escaping (T) -> A, @ViewBuilder message: @escaping (T) -> M ) -> some View { self.alert( data.wrappedValue.map(title) ?? Text(""), isPresented: ???, presenting: data.wrappedValue, actions: actions, message: message ) } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞ͳ͍ API overloads

Slide 109

Slide 109 text

Optional item ͷΈΛཁٻ͢Δ API Λߟ͑Δ extension View { func alert( title: (T) -> Text, presenting data: Binding, @ViewBuilder actions: @escaping (T) -> A, @ViewBuilder message: @escaping (T) -> M ) -> some View { self.alert( data.wrappedValue.map(title) ?? Text(""), isPresented: ???, // Binding Λ Binding ʹม׵Ͱ͖Δͱྑͦ͞͏ presenting: data.wrappedValue, actions: actions, message: message ) } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞ͳ͍ API overloads

Slide 110

Slide 110 text

Binding Λ Binding ʹม׵͢Δ extension Binding { func isPresented() -> Binding where Value == Wrapped? { .init( get: { self.wrappedValue != nil }, set: { isPresented in if !isPresented { self.wrappedValue = nil } } ) } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞ͳ͍ API overloads

Slide 111

Slide 111 text

Binding Λ Binding ʹม׵͢Δ extension Binding { func isPresented() -> Binding where Value == Wrapped? { // Binding Λม׵͢ΔͨΊͷ΋ͷͳͷͰɺoptional ʹݶఆ .init( get: { self.wrappedValue != nil }, set: { isPresented in if !isPresented { self.wrappedValue = nil } } ) } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞ͳ͍ API overloads

Slide 112

Slide 112 text

Binding Λ Binding ʹม׵͢Δ extension Binding { func isPresented() -> Binding where Value == Wrapped? { .init( get: { self.wrappedValue != nil }, set: { isPresented in // isPresent ͕ false = alert ͕ด͡ΒΕΔλΠϛϯά // ͦͷࡍ͸ Binding ࣗ਎Λ nil ʹ͢Δ͜ͱͰແޮͳঢ়ଶͷൃੜΛ๷͛Δ if !isPresented { self.wrappedValue = nil } } ) } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞ͳ͍ API overloads

Slide 113

Slide 113 text

࡞੒ͨ͠ isPresented Λద༻͢Δ extension View { func alert( title: (T) -> Text, presenting data: Binding, @ViewBuilder actions: @escaping (T) -> A, @ViewBuilder message: @escaping (T) -> M ) -> some View { self.alert( data.wrappedValue.map(title) ?? Text(""), isPresented: data.isPresented(), presenting: data.wrappedValue, actions: actions, message: message ) } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞ͳ͍ API overloads

Slide 114

Slide 114 text

Before / After struct ExampleView: View { @State private var item: Item? var body: some View { BaseView(...) .alert( Text($0.xxx), presenting: item action: { item in ... }, message: { item in ... } ) } } struct ExampleView: View { @State private var showAlert = false @State private var item: Item? var body: some View { BaseView(...) .alert( "Alert title", isPresented: $showAlert, presenting: item action: { item in ... }, message: { item in ... } ) } } #FGPSF "GUFS Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞ͳ͍ API overloads

Slide 115

Slide 115 text

ʮswiftui-navigation ʯͷΞϓϩʔν 1. ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ • Binding value Λ౉͢͜ͱ͕Ͱ͖Δ API overloads 2. ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ • ࠷௿ݶͷঢ়ଶͷΈΛཁٻ͢Δ API overloads 3. ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ • Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 116

Slide 116 text

ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱ 
 ແବͳঢ়ଶ͕૿͑Δ struct ContentView: View { @State var draft: Post? // null + non null = 2 @State var settings: Settings? // null + non null = 2 @State var userProfile: Profile? // null + non null = 2 var body: some View { BaseView(...) .sheet(item: self.$draft) { (draft: Post) in EditPostView(post: draft) } .sheet(item: self.$settings) { (settings: Settings) in SettingsView(settings: settings) } .sheet(item: self.$userProfile) { (userProfile: Profile) in UserProfile(profile: userProfile) } } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 117

Slide 117 text

༷ʑͳύλʔϯͷঢ়ଶ͕ൃੜͯ͠͠·͏ %SBGU 4FUUJOHT 1SP fi MF ύλʔϯ /VMM /VMM /VMM ύλʔϯ /POOVMM /VMM /VMM ύλʔϯ /VMM /POOVMM /VMM ύλʔϯ /VMM /VMM /POOVMM ύλʔϯ /POOVMM /POOVMM /VMM ύλʔϯ /POOVMM /VMM /POOVMM ύλʔϯ /VMM /POOVMM /POOVMM ύλʔϯ /POOVMM /POOVMM /POOVMM Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 118

Slide 118 text

༷ʑͳύλʔϯͷঢ়ଶ͕ൃੜͯ͠͠·͏ %SBGU 4FUUJOHT 1SP fi MF ύλʔϯ /VMM /VMM /VMM ύλʔϯ /POOVMM /VMM /VMM ύλʔϯ /VMM /POOVMM /VMM ύλʔϯ /VMM /VMM /POOVMM ύλʔϯ /POOVMM /POOVMM /VMM ύλʔϯ /POOVMM /VMM /POOVMM ύλʔϯ /VMM /POOVMM /POOVMM ύλʔϯ /POOVMM /POOVMM /POOVMM ༗ޮͳঢ়ଶ͸͜ΕΒͷΈ Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 119

Slide 119 text

ෳ਺ͷ Navigation ͷ࠷దͳϞσϦϯάΛߟ͑Δ // Navigation ͸ಉ࣌ʹෳ਺ൃੜ͢Δ͜ͱ͕ͳ͍ͨΊɺ΋ͬͱྑ͍ϞσϦϯά͕Ͱ͖ͦ͏ @State var draft: Post? @State var settings: Settings? @State var userProfile: Profile? Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 120

Slide 120 text

ෳ਺ͷ Navigation ͷ࠷దͳϞσϦϯάΛߟ͑Δ // ಉ࣌ʹෳ਺ൃੜ͠ͳ͍ = enum Λ࢖͑Δ @State var draft: Post? @State var settings: Settings? @State var userProfile: Profile? " enum Route { case draft(Post) case settings(Settings) case userProfile(Profile) } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 121

Slide 121 text

enum Ͱ sheet ͳͲΛදࣔ͠Α͏ͱ͢Δͱʁ struct ExampleView: View { @State private var route: Route? // ... .sheet( item: Binding( get: { if case let .draft(post) = route return post } else { return nil } }, set: { post if let post = post { route = .draft(post) } } ) ) { post in /* ... */ } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 122

Slide 122 text

enum Ͱ sheet ͳͲΛදࣔ͠Α͏ͱ͢Δͱʁ struct ExampleView: View { @State private var route: Route? // ... .sheet( item: Binding( get: { if case let .draft(post) = route return post } else { return nil } }, set: { post if let post = post { route = .draft(post) } } ) ) { post in /* ... */ } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 123

Slide 123 text

enum Ͱ sheet ͳͲΛදࣔ͠Α͏ͱ͢Δͱʁ struct ExampleView: View { @State private var route: Route? // ... .sheet( item: Binding( get: { if case let .draft(post) = route return post } else { return nil } }, set: { post if let post = post { route = .draft(post) } } ) ) { post in /* ... */ } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 124

Slide 124 text

enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ struct ExampleView: View { @State private var route: Route? // ... .sheet( unwrapping: $route, case: ???Route.draft??? ) { $post in // ... } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 125

Slide 125 text

enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ struct ExampleView: View { @State private var route: Route? // ... .sheet( unwrapping: $route, // enum ࣗମΛ౉͢ (Binding value) case: ???Route.draft??? ) { $post in // ... } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 126

Slide 126 text

enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ struct ExampleView: View { @State private var route: Route? // ... .sheet( unwrapping: $route, case: ???Route.draft??? // ԿΒ͔ͷܗͰ enum ͷಛఆͷ case Λࢦఆ͢Δ ) { $post in // ... } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 127

Slide 127 text

enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ struct ExampleView: View { @State private var route: Route? // ... .sheet( unwrapping: $route, case: ???Route.draft??? ) { $post in // Associated value Λ binding value Ͱ౉ͤΔͱͳ͓ྑ͍ // ... } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 128

Slide 128 text

enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View { func sheet( unwrapping: ???, // enum ͷ binding case: ???, // enum ͷಛఆͷ case @ViewBuilder content: @escaping (Binding??>) -> Content ) -> some View where Content: View { // ... } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 129

Slide 129 text

enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View { func sheet( unwrapping: ???, // enum ͷ binding case: ???, // enum ͷಛఆͷ case @ViewBuilder content: @escaping (Binding??>) -> Content ) -> some View where Content: View { // ... } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 130

Slide 130 text

enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View { func sheet( unwrapping: Binding, // enum ͷ binding case: ???, // enum ͷಛఆͷ case @ViewBuilder content: @escaping (Binding??>) -> Content ) -> some View where Content: View { // ... } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 131

Slide 131 text

enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View { func sheet( unwrapping: Binding, // enum ͷ binding case: ???, // enum ͷಛఆͷ case @ViewBuilder content: @escaping (Binding??>) -> Content ) -> some View where Content: View { // ... } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 132

Slide 132 text

enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View { func sheet( unwrapping: Binding, // enum ͷ binding case: CasePath, // enum ͷಛఆͷ case @ViewBuilder content: @escaping (Binding??>) -> Content ) -> some View where Content: View { // ... } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 133

Slide 133 text

enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View { func sheet( unwrapping: Binding, // enum ͷ binding case: CasePath, // enum ͷಛఆͷ case @ViewBuilder content: @escaping (Binding??>) -> Content ) -> some View where Content: View { // ... } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads [CasePaths] • https://github.com/pointfreeco/swift-case-paths • struct ʹ͓͚Δ Key Paths ͷ enum ൛ͷΑ͏ͳ΋ͷ • Key Paths ͸ `\User.id` ͱ͢Δ͕ɺCase Paths ͸ `/Kind.animal` • Enum ͔Βʮಛఆͷ Case ͷநग़ʯɾʮಛఆͷ Case ΁ͷ Associated value ͷ
 ຒΊࠐΈʯΛ͍ͨ͠༻్Ͱར༻͍ͯ͠Δ

Slide 134

Slide 134 text

enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View { func sheet( unwrapping: Binding, // enum ͷ binding case: CasePath, // enum ͷಛఆͷ case @ViewBuilder content: @escaping (Binding??>) -> Content ) -> some View where Content: View { // ... } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 135

Slide 135 text

enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View { func sheet( unwrapping: Binding, // enum ͷ binding case: CasePath, // enum ͷಛఆͷ case // AssociatedValue ͕͋Ε͹ͦΕΛར༻Ͱ͖Δ (ͳ͚Ε͹ Void) Binding @ViewBuilder content: @escaping (Binding) -> Content ) -> some View where Content: View { // ... } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 136

Slide 136 text

enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View { func sheet( unwrapping enum: Binding, case casePath: CasePath, @ViewBuilder content: @escaping (Binding) -> Content ) -> some View where Content: View { self.sheet( isPresented: ??? ) { ??? } } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 137

Slide 137 text

enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View { func sheet( unwrapping enum: Binding, case casePath: CasePath, @ViewBuilder content: @escaping (Binding) -> Content ) -> some View where Content: View { self.sheet( isPresented: ??? ) { ??? } } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 138

Slide 138 text

enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View { func sheet( unwrapping enum: Binding, case casePath: CasePath, @ViewBuilder content: @escaping (Binding) -> Content ) -> some View where Content: View { self.sheet( isPresented: `enum`.case(casePath).isPresented() ) { ??? } } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 139

Slide 139 text

enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View { func sheet( unwrapping enum: Binding, case casePath: CasePath, @ViewBuilder content: @escaping (Binding) -> Content ) -> some View where Content: View { self.sheet( isPresented: `enum`.case(casePath).isPresented() ) { ??? } } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads case(casePath) ͸ Case Paths Λར༻ͨ͠ function Binding ͔Β Binding Λநग़͢Δ

Slide 140

Slide 140 text

enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View { func sheet( unwrapping enum: Binding, case casePath: CasePath, @ViewBuilder content: @escaping (Binding) -> Content ) -> some View where Content: View { self.sheet( isPresented: `enum`.case(casePath).isPresented() ) { ??? } } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads `enum`.case(casePath) " Binding case(casePath) ͸ Case Paths Λར༻ͨ͠ function Binding ͔Β Binding Λநग़͢Δ

Slide 141

Slide 141 text

enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View { func sheet( unwrapping enum: Binding, case casePath: CasePath, @ViewBuilder content: @escaping (Binding) -> Content ) -> some View where Content: View { self.sheet( isPresented: `enum`.case(casePath).isPresented() ) { ??? } } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads `enum`.case(casePath) " Binding `enum`.case(casePath) .isPresented() " Binding case(casePath) ͸ Case Paths Λར༻ͨ͠ function Binding ͔Β Binding Λநग़͢Δ

Slide 142

Slide 142 text

enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View { func sheet( unwrapping enum: Binding, case casePath: CasePath, @ViewBuilder content: @escaping (Binding) -> Content ) -> some View where Content: View { self.sheet( isPresented: `enum`.case(casePath).isPresented() ) { ??? } } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 143

Slide 143 text

enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View { func sheet( unwrapping enum: Binding, case casePath: CasePath, @ViewBuilder content: @escaping (Binding) -> Content ) -> some View where Content: View { self.sheet( isPresented: `enum`.case(casePath).isPresented() ) { Binding( unwrapping: `enum`.case(casePath) ).map(content) } } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 144

Slide 144 text

enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View { func sheet( unwrapping enum: Binding, case casePath: CasePath, @ViewBuilder content: @escaping (Binding) -> Content ) -> some View where Content: View { self.sheet( isPresented: `enum`.case(casePath).isPresented() ) { Binding( unwrapping: `enum`.case(casePath) ).map(content) } } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads `enum`.case(casePath) " Binding

Slide 145

Slide 145 text

enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View { func sheet( unwrapping enum: Binding, case casePath: CasePath, @ViewBuilder content: @escaping (Binding) -> Content ) -> some View where Content: View { self.sheet( isPresented: `enum`.case(casePath).isPresented() ) { Binding( unwrapping: `enum`.case(casePath) ).map(content) } } } Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads `enum`.case(casePath) " Binding Binding(unwrapping:) " Binding " map

Slide 146

Slide 146 text

Before / After struct ContentView: View { enum Route { // ... } @State var route: Route? var body: some View { BaseView(...) .sheet( unwrapping: $route, case: /Route.draft ) { $draft in EditPostView(post: $draft) } // ... } } struct ContentView: View { @State var draft: Post? @State var settings: Settings? @State var userProfile: Profile? var body: some View { BaseView(...) .sheet(item: self.$draft) { draft in EditPostView(post: draft) } .sheet(item: self.$settings) { settings in SettingsView(settings: settings) } .sheet(item: self.$userProfile) { userProfile in UserProfile(profile: userProfile) } } } #FGPSF "GUFS Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads

Slide 147

Slide 147 text

Navigation API ͷվળʹΑΔޮՌ • SwiftUI ͷ Navigation API ʹ͓͚Δ ՝୊Λ API overloads ͱ͍͏ 
 γϯϓϧͳํ๏ͰղܾͰ͖ͨ (ϥΠϒϥϦͷ࣮૷͸΋ͬͱચ࿅͞Ε͍ͯ·͢) 1. ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ 2. ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ 3. ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ • Navigation API ͕ΑΓ҆શͰѻ͍΍͘͢ͳΓɺNavigation ʹؔΘΔঢ়ଶͷ؅ཧ΋ ༰қʹͳΔ Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔

Slide 148

Slide 148 text

·ͱΊ

Slide 149

Slide 149 text

·ͱΊ • SwiftUI ʹ͸༷ʑͳ Navigation API ͕͋ΓɺOS ͱڞʹܹ͍͠มԽ͕ ͋ͬͨ • େ͖͘ Navigation API ͸ҎԼͷ 2 छྨʹ۠ผͰ͖Δ • Fire and forget API • State driven API

Slide 150

Slide 150 text

·ͱΊ • SwiftUI ͷ Navigation API ʹ͸ҎԼͷΑ͏ͳ՝୊͕͋ΓɺAPI Λద੾ʹ overload ͯ͠ղܾ͢Δ 
 ʮswiftui-navigationʯͷΑ͏ͳΞϓϩʔν΋ଘࡏ͍ͯ͠Δ • ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ • ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ • ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ • SwiftUI ͷ Navigation Λਖ਼͘͠ཧղͯ͠؅ཧ͢Ε͹৭ʑͳԸܙ͕͋Δ • Navigation ʹؔΘΔঢ়ଶ؅ཧʹ೰·͞Εͳ͍ • Deep Link ͕༰қʹͳΔɾXcode Previews ΋׆༻͠΍͘͢ͳΔ

Slide 151

Slide 151 text

ࢀߟ • https://www.pointfree.co/collections/swiftui/navigation • https://gist.github.com/mbrandonw/f8b94957031160336cac6898a919cbb7 • https://github.com/pointfreeco/swift-composable-architecture/discussions/1140 • https://developer.apple.com/documentation/swiftui • https://github.com/pointfreeco/swiftui-navigation • https://swiftwithmajid.com/2022/06/15/mastering-navigationstack-in-swiftui-navigator- pattern/ • https://swiftwithmajid.com/2022/06/21/mastering-navigationstack-in-swiftui-deep- linking/

Slide 152

Slide 152 text

After Party iOSDC ͥͻ͝ࢀՃ͍ͩ͘͞ʂ