Upgrade to Pro — share decks privately, control downloads, hide ads and more …

SwiftUI Navigation のすべて

Aikawa
September 10, 2022

SwiftUI Navigation のすべて

iOSDC Japan 2022 で発表した内容です

Aikawa

September 10, 2022
Tweet

More Decks by Aikawa

Other Decks in Programming

Transcript

  1. SwiftUI Navigation ͷ͢΂ͯ iOSDC Japan 2022 kalupas226

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

    2
  3. ΞδΣϯμ • SwiftUI Navigation ͷ၆ᛌ • ༷ʑͳछྨ ͷ Navigation •

    OS ʹΑΔมԽ͕ܹ͍͠ Navigation • Fire and forget / State driven Navigation API • SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ • Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ • ʮswiftui-navigationʯͷΞϓϩʔν • ·ͱΊ 3
  4. 􀁟 ຊτʔΫͰ࿩͞ͳ͍͜ͱ • ։ൃऀ͕ͦΕͧΕͰఆٛ͢Δಠࣗͷ Custom Navigation • iOS Ҏ֎ͷϓϥοτϑΥʔϜʹ͓͚Δ Navigation

    • ΞϓϦέʔγϣϯʹ͓͚Δ Navigation ͸͜͏͋Δ΂͖ͱ͍͏Α͏ͳ 
 σβΠϯతͳ࿩ 4
  5. 􀁟 ຊτʔΫͰओʹࢀߟʹ͍ͯ͠Δ৘ใ • Point-Free ੡ͷʮswiftui-navigationʯͱ͍͏ϥΠϒϥϦ • https://github.com/pointfreeco/swiftui-navigation • ൃද಺Ͱ͸ҎԼͷΑ͏ʹ۠ผͯ͠આ໌͠·͢ •

    SwiftUI Navigation API: Apple ७ਖ਼ͷ API ʹ͍ͭͯͷ࿩ • ʮswiftui-navigationʯ: ϥΠϒϥϦʹ͍ͭͯͷ࿩ 5
  6. SwiftUI Navigation ͷ၆ᛌ

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

  8. ༷ʑͳछྨͷ Navigation API ͕ଘࡏ͢Δ • Tab • Alert • Sheet

    • Full Screen Cover • Con fi rmation Dialog • Popover • Navigation Link… SwiftUI Navigation ͷ၆ᛌ > ༷ʑͳछྨͷ Navigation 8
  9. Tab TabView { FirstView() .tabItem { Image(systemName: "exclamationmark.circle") Text("Alert") }

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

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

    SwiftUI Navigation ͷ၆ᛌ > ༷ʑͳछྨͷ Navigation
  12. 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
  13. SwiftUI Navigation ͷ၆ᛌ OS ʹΑΔมԽ͕ܹ͍͠ Navigation

  14. OS ͕ਐԽ͢ΔʹͭΕ API ͷܗ΋มΘ͖ͬͯͨ • ActionSheet API (deprecated) → Con

    fi rmation Dialog API • Alert API • deprecated ʹͳͬͨ΋ͷͱɺͦ͏Ͱͳ͍΋ͷ͕͋Δ • Navigation-base API • NavigationView → NavigationStack • NavigationLink 14 SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation
  15. ActionSheet API (deprecated) .actionSheet(isPresented: $showActionSheet) { ActionSheet( title: Text(...), message:

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

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

    Text(...), buttons: [ .cancel(), .destructive( Text(...), action: {} ), .default( Text(...), action: {} ) ] ) } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation
  18. 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
  19. 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
  20. 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
  21. Alert API (deprecated) .alert(isPresented: $showAlert) { Alert( title: Text("Title"), message:

    Text("Message") ) } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation
  22. 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
  23. Alert API (iOS 15~) .alert( "Alert͕දࣔ͞Ε·ͨ͠", isPresented: $isPresentedAlert, actions: {

    Button("OK", action: {}) } ) SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation
  24. NavigationViewɾOld NavigationLink (deprecated) NavigationView { List(model.notes) { note in NavigationLink(

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

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

    note.title, // ભҠݩͷ View ʹදࣔ͞ΕΔ title destination: NoteEditor(id: note.id) // ભҠޙͷը໘ ) } } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation
  27. 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
  28. 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
  29. 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
  30. 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
  31. 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
  32. 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
  33. 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
  34. SwiftUI Navigation ͷ၆ᛌ Fire and forget / State driven Navigation

    API
  35. 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
  36. Navigation API ͸େ͖͘ 2 ͭʹ෼ྨͰ͖Δ • Fire and forget Navigation

    API • State driven Navigation API 36 SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API
  37. Fire and forget Navigation API • Binding Ҿ਺ΛऔΒͳ͍ • SwiftUI

    ͕ Navigation ͷঢ়ଶΛ׬શʹ಺෦Ͱ؅ཧ͢Δ • Navigation Λૉૣ࣮͘ݱͰ͖Δ͕ɺNavigation ʹରͯ͠ 
 ϓϩάϥϜతͳ੍ޚ͕Ͱ͖ͳ͘ͳΔ 37 SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API
  38. Fire and forget API - Tab - TabView { ReceivedView()

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

    navigation Ͱ͖ͳ͍ TabView { ReceivedView() .tabItem { // ... } SentView() .tabItem { // ... } AccountView() .tabItem { // ... } } SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API
  40. 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
  41. 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
  42. Navigation API ͸େ͖͘ 2 ͭʹ෼ྨͰ͖Δ • Fire and forget Navigation

    API • State driven Navigation API 42 SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API
  43. State driven Navigation API • Binding Ҿ਺ΛऔΔ • Navigation Λ༗ޮɾແޮʹ͢Δ࣌ʹυϝΠϯͷঢ়ଶ΋มߋͰ͖Δ

    • Fire and forget API ΑΓෳࡶͰ͸͋Δ͕ɺϓϩάϥϜతͳ੍ޚ͕ 
 ՄೳͱͳΔͨΊɺ࢖͍ํʹΑͬͯ͸ Deep Link ͳͲ΋࣮ݱͰ͖Δ 43 SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API
  44. 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
  45. 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
  46. 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
  47. ҟͳΔ View ͰแΉͱ Deep Link Ͱ͖ͳ͍ struct ContainerView: View {

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

    body: some View { ContentView(selectedTab: selectedTab) } } SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API
  49. 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
  50. ΞϓϦͷঢ়ଶΛ؅ཧ͢Δ ViewModel Λಋೖ͠ 
 ղܾ͢Δ class AppViewModel: ObservableObject { @Published

    var selectedTab: Tab init(selectedTab: Tab = .received) { self.selectedTab = selectedTab } } SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API
  51. ΞϓϦͷঢ়ଶΛ؅ཧ͢Δ 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
  52. SwiftUI ͷ Navigation API 
 ʹ͓͚Δ՝୊

  53. Navigation API ʹ͓͚Δ՝୊ 1. ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ 2. ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ

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

    API ͕ଘࡏ͍ͯ͠Δ 3. ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍
  55. ભҠઌͷը໘ʹ 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 Λ౉͢ػߏΛඋ͍͑ͯͳ͍
  56. ભҠઌͷը໘ʹ 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 Λ౉͢ػߏΛඋ͍͑ͯͳ͍
  57. ભҠઌͷը໘ʹ 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 ʹ൓ө͞Εͳ͍
  58. Navigation API ʹ͓͚Δ՝୊ 1. ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ 2. ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ

    API ͕ଘࡏ͍ͯ͠Δ 3. ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ
  59. Deprecated / New Alert API // Deprecated API // Binding<Bool>

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

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

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

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

    Λड͚औΔ func alert( isPresented: Binding<Bool>, content: () -> Alert ) -> some View // Binding<Item?> Λड͚औΔ func alert<Item>( item: Binding<Item?>, content: (Item) -> Alert ) -> some View where Item : Identifiable // New API // Binding<Bool> Λड͚औΔ func alert<A>( _ title: Text, isPresented: Binding<Bool>, actions: () -> A ) -> some View where A : View // Binding<Bool> ͱ data Λड͚औΔ func alert<A, T>( _ title: Text, isPresented: Binding<Bool>, presenting data: T?, actions: (T) -> A ) -> some View where A : View SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ
  67. 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 ͕ଘࡏ͍ͯ͠Δ
  68. 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
  69. 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
  70. New boolean binding and optional item API ͸ 
 ঢ়ଶ؅ཧΛෳࡶʹͤͯ͞͠·͏

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

    API ͕ଘࡏ͍ͯ͠Δ 3. ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ SwiftUI ͷ Navigation API ʹ͓͚Δ՝୊ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ
  72. ෳ਺ͷ 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 Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ
  73. ෳ਺ͷ 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 Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ
  74. ෳ਺ͷ 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 Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ
  75. ༷ʑͳύλʔϯͷঢ়ଶ͕ൃੜͯ͠͠·͏ %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 Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ
  76. ༷ʑͳύλʔϯͷঢ়ଶ͕ൃੜͯ͠͠·͏ %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 Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ
  77. Navigation API ͷ՝୊ʹ 
 Ͳ͏ཱͪ޲͔͏͔

  78. Navigation API ʹ͓͚Δ՝୊ 1. ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ 2. ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ

    API ͕ଘࡏ͍ͯ͠Δ 3. ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔
  79. ʮswiftui-navigation ʯͷΞϓϩʔν 1. ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ • Binding value

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

    Λ౉͢͜ͱ͕Ͱ͖Δ API overloads 2. ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ • ࠷௿ݶͷঢ়ଶͷΈΛཁٻ͢Δ API overloads 3. ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ • Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔
  82. ʮ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
  83. ભҠઌͷը໘ʹ 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
  84. ભҠઌͷը໘ʹ 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 ʹ൓ө͞Εͳ͍
  85. 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
  86. 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
  87. Binding Value Λ౉ͤΔ sheet API Λߟ͑Δ extension View { func

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

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

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

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

    { 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
  92. Binding<Value?> Λ Binding<Value> ʹม׵͢Δ extension Binding { init?(unwrapping binding: Binding<Value?>)

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

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

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

    optionalValue: Binding<Value?>, @ViewBuilder content: @escaping (Binding<Value>) -> 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
  96. ࡞੒ͨ͠ init?(unwrapping:) Λద༻͢Δ extension View { func sheet<Value, Content>( unwrapping

    optionalValue: Binding<Value?>, @ViewBuilder content: @escaping (Binding<Value>) -> 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
  97. 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
  98. ʮswiftui-navigation ʯͷΞϓϩʔν 1. ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ • Binding value

    Λ౉͢͜ͱ͕Ͱ͖Δ API overloads 2. ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ • ࠷௿ݶͷঢ়ଶͷΈΛཁٻ͢Δ API overloads 3. ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ • Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ > ࠷௿ݶͷঢ়ଶͷΈΛཁٻ͢Δ API overloads
  99. ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ 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
  100. ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ 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
  101. ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ 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
  102. ͳͥঢ়ଶ؅ཧΛෳࡶʹ͢Δ 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
  103. ঢ়ଶ؅ཧΛෳࡶʹͤ͞ͳ͍ 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
  104. Optional item ͷΈΛཁٻ͢Δ API Λߟ͑Δ extension View { func alert<A:

    View, M: View, T>( title: (T) -> Text, presenting data: Binding<T?>, @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
  105. Optional item ͷΈΛཁٻ͢Δ API Λߟ͑Δ extension View { func alert<A:

    View, M: View, T>( title: (T) -> Text, presenting data: Binding<T?>, @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
  106. Optional item ͷΈΛཁٻ͢Δ API Λߟ͑Δ extension View { func alert<A:

    View, M: View, T>( title: (T) -> Text, presenting data: Binding<T?>, @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
  107. Optional item ͷΈΛཁٻ͢Δ API Λߟ͑Δ extension View { func alert<A:

    View, M: View, T>( title: (T) -> Text, presenting data: Binding<T?>, @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
  108. Optional item ͷΈΛཁٻ͢Δ API Λߟ͑Δ extension View { func alert<A:

    View, M: View, T>( title: (T) -> Text, presenting data: Binding<T?>, @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
  109. Optional item ͷΈΛཁٻ͢Δ API Λߟ͑Δ extension View { func alert<A:

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

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

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

    Binding<Bool> 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
  113. ࡞੒ͨ͠ isPresented Λద༻͢Δ extension View { func alert<A: View, M:

    View, T>( title: (T) -> Text, presenting data: Binding<T?>, @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
  114. 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
  115. ʮ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
  116. ෳ਺ͷ 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
  117. ༷ʑͳύλʔϯͷঢ়ଶ͕ൃੜͯ͠͠·͏ %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
  118. ༷ʑͳύλʔϯͷঢ়ଶ͕ൃੜͯ͠͠·͏ %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
  119. ෳ਺ͷ Navigation ͷ࠷దͳϞσϦϯάΛߟ͑Δ // Navigation ͸ಉ࣌ʹෳ਺ൃੜ͢Δ͜ͱ͕ͳ͍ͨΊɺ΋ͬͱྑ͍ϞσϦϯά͕Ͱ͖ͦ͏ @State var draft: Post?

    @State var settings: Settings? @State var userProfile: Profile? Navigation API ͷ՝୊ʹͲ͏ཱͪ޲͔͏͔ > ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum Ͱ؅ཧͰ͖ΔΑ͏ʹ͢Δ API overloads
  120. ෳ਺ͷ 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
  121. enum Ͱ sheet ͳͲΛදࣔ͠Α͏ͱ͢Δͱʁ struct ExampleView: View { @State private

    var route: Route? // ... .sheet( item: Binding<Post?>( 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
  122. enum Ͱ sheet ͳͲΛදࣔ͠Α͏ͱ͢Δͱʁ struct ExampleView: View { @State private

    var route: Route? // ... .sheet( item: Binding<Post?>( 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
  123. enum Ͱ sheet ͳͲΛදࣔ͠Α͏ͱ͢Δͱʁ struct ExampleView: View { @State private

    var route: Route? // ... .sheet( item: Binding<Post?>( 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
  124. 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
  125. 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
  126. 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
  127. 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
  128. enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View<Content> { 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
  129. enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View<Content> { 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
  130. enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View<Enum, Content> { func

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

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

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

    func sheet( unwrapping: Binding<Enum?>, // enum ͷ binding case: CasePath<Enum, Case>, // 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 ͷ
 ຒΊࠐΈʯΛ͍ͨ͠༻్Ͱར༻͍ͯ͠Δ
  134. enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View<Enum, Case, Content> {

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

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

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

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

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

    Case, Content>( unwrapping enum: Binding<Enum?>, case casePath: CasePath<Enum, Case>, @ViewBuilder content: @escaping (Binding<Case>) -> 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<Enum?> ͔Β Binding<Case?> Λநग़͢Δ
  140. enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View { func sheet<Enum,

    Case, Content>( unwrapping enum: Binding<Enum?>, case casePath: CasePath<Enum, Case>, @ViewBuilder content: @escaping (Binding<Case>) -> 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?> case(casePath) ͸ Case Paths Λར༻ͨ͠ function Binding<Enum?> ͔Β Binding<Case?> Λநग़͢Δ
  141. enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View { func sheet<Enum,

    Case, Content>( unwrapping enum: Binding<Enum?>, case casePath: CasePath<Enum, Case>, @ViewBuilder content: @escaping (Binding<Case>) -> 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?> `enum`.case(casePath) .isPresented() " Binding<Bool> case(casePath) ͸ Case Paths Λར༻ͨ͠ function Binding<Enum?> ͔Β Binding<Case?> Λநग़͢Δ
  142. enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View { func sheet<Enum,

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

    Case, Content>( unwrapping enum: Binding<Enum?>, case casePath: CasePath<Enum, Case>, @ViewBuilder content: @escaping (Binding<Case>) -> 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
  144. enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View { func sheet<Enum,

    Case, Content>( unwrapping enum: Binding<Enum?>, case casePath: CasePath<Enum, Case>, @ViewBuilder content: @escaping (Binding<Case>) -> 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<Case?>
  145. enum Ͱ΋ѻ͍΍͍͢ sheet API Λߟ͑Δ extension View { func sheet<Enum,

    Case, Content>( unwrapping enum: Binding<Enum?>, case casePath: CasePath<Enum, Case>, @ViewBuilder content: @escaping (Binding<Case>) -> 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<Case?> Binding(unwrapping:) " Binding<Case> " map
  146. 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
  147. Navigation API ͷվળʹΑΔޮՌ • SwiftUI ͷ Navigation API ʹ͓͚Δ ՝୊Λ

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

  149. ·ͱΊ • SwiftUI ʹ͸༷ʑͳ Navigation API ͕͋ΓɺOS ͱڞʹܹ͍͠มԽ͕ ͋ͬͨ •

    େ͖͘ Navigation API ͸ҎԼͷ 2 छྨʹ۠ผͰ͖Δ • Fire and forget API • State driven API
  150. ·ͱΊ • SwiftUI ͷ Navigation API ʹ͸ҎԼͷΑ͏ͳ՝୊͕͋ΓɺAPI Λద੾ʹ overload ͯ͠ղܾ͢Δ

    
 ʮswiftui-navigationʯͷΑ͏ͳΞϓϩʔν΋ଘࡏ͍ͯ͠Δ • ભҠઌͷը໘ʹ Binding value Λ౉͢ػߏΛඋ͍͑ͯͳ͍ • ঢ়ଶ؅ཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ • ෳ਺ͷ Navigation Λ؅ཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ • SwiftUI ͷ Navigation Λਖ਼͘͠ཧղͯ͠؅ཧ͢Ε͹৭ʑͳԸܙ͕͋Δ • Navigation ʹؔΘΔঢ়ଶ؅ཧʹ೰·͞Εͳ͍ • Deep Link ͕༰қʹͳΔɾXcode Previews ΋׆༻͠΍͘͢ͳΔ
  151. ࢀߟ • 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/
  152. After Party iOSDC ͥͻ͝ࢀՃ͍ͩ͘͞ʂ