Share
Embed
Transcript
152 slides
-
ΞδΣϯμ • SwiftUI Navigation ͷ၆ᛌ • ༷ʑͳछྨ ͷ Navigation •
OS ʹΑΔมԽ͕ܹ͍͠ Navigation • Fire and forget / State driven Navigation API • SwiftUI ͷ Navigation API ʹ͓͚Δ՝ • Navigation API ͷ՝ʹͲ͏ཱ͔ͪ͏͔ • ʮswiftui-navigationʯͷΞϓϩʔν • ·ͱΊ 3 -
ຊτʔΫͰ͞ͳ͍͜ͱ • ։ൃऀ͕ͦΕͧΕͰఆٛ͢Δಠࣗͷ Custom Navigation • iOS Ҏ֎ͷϓϥοτϑΥʔϜʹ͓͚Δ Navigation
• ΞϓϦέʔγϣϯʹ͓͚Δ Navigation ͜͏͋Δ͖ͱ͍͏Α͏ͳ σβΠϯతͳ 4 -
ຊτʔΫͰओʹࢀߟʹ͍ͯ͠Δใ • Point-Free ͷʮswiftui-navigationʯͱ͍͏ϥΠϒϥϦ • https://github.com/pointfreeco/swiftui-navigation • ൃදͰҎԼͷΑ͏ʹ۠ผͯ͠આ໌͠·͢ •
SwiftUI Navigation API: Apple ७ਖ਼ͷ API ʹ͍ͭͯͷ • ʮswiftui-navigationʯ: ϥΠϒϥϦʹ͍ͭͯͷ 5 -
༷ʑͳछྨͷ Navigation API ͕ଘࡏ͢Δ • Tab • Alert • Sheet
• Full Screen Cover • Con fi rmation Dialog • Popover • Navigation Link… SwiftUI Navigation ͷ၆ᛌ > ༷ʑͳछྨͷ Navigation 8 -
Tab TabView { FirstView() .tabItem { Image(systemName: "exclamationmark.circle") Text("Alert") }
SecondView() .tabItem {…} ThirdView() .tabItem {…} FourthView() .tabItem {…} } SwiftUI Navigation ͷ၆ᛌ > ༷ʑͳछྨͷ Navigation -
Alert BaseView() .alert( “Alert͕දࣔ͞Ε·ͨ͠”, isPresented: $isPresentedAlert, actions: { Button("OK", action:
{}) } ) SwiftUI Navigation ͷ၆ᛌ > ༷ʑͳछྨͷ Navigation -
Sheet BaseView() .sheet( isPresented: $isPresentedAlert, content: { Text("Sheet͕දࣔ͞Ε·ͨ͠") } )
SwiftUI Navigation ͷ၆ᛌ > ༷ʑͳछྨͷ Navigation -
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 -
OS ͕ਐԽ͢ΔʹͭΕ API ͷܗมΘ͖ͬͯͨ • ActionSheet API (deprecated) → Con
fi rmation Dialog API • Alert API • deprecated ʹͳͬͨͷͱɺͦ͏Ͱͳ͍ͷ͕͋Δ • Navigation-base API • NavigationView → NavigationStack • NavigationLink 14 SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation -
ActionSheet API (deprecated) .actionSheet(isPresented: $showActionSheet) { ActionSheet( title: Text(...), message:
Text(...), buttons: [ .cancel(), .destructive( Text(...), action: {} ), .default( Text(...), action: {} ) ] ) } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation -
ActionSheet API (deprecated) .actionSheet(isPresented: $showActionSheet) { ActionSheet( title: Text(...), message:
Text(...), buttons: [ .cancel(), .destructive( Text(...), action: {} ), .default( Text(...), action: {} ) ] ) } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation -
ActionSheet API (deprecated) .actionSheet(isPresented: $showActionSheet) { ActionSheet( title: Text(...), message:
Text(...), buttons: [ .cancel(), .destructive( Text(...), action: {} ), .default( Text(...), action: {} ) ] ) } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation -
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 -
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 -
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 -
Alert API (deprecated) .alert(isPresented: $showAlert) { Alert( title: Text("Title"), message:
Text("Message") ) } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation -
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 -
Alert API (iOS 15~) .alert( "Alert͕දࣔ͞Ε·ͨ͠", isPresented: $isPresentedAlert, actions: {
Button("OK", action: {}) } ) SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation -
NavigationViewɾOld NavigationLink (deprecated) NavigationView { List(model.notes) { note in NavigationLink(
note.title, destination: NoteEditor(id: note.id) ) } } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation -
NavigationViewɾOld NavigationLink (deprecated) NavigationView { List(model.notes) { note in NavigationLink(
note.title, destination: NoteEditor(id: note.id) ) } } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation -
NavigationViewɾOld NavigationLink (deprecated) NavigationView { List(model.notes) { note in NavigationLink(
note.title, // ભҠݩͷ View ʹදࣔ͞ΕΔ title destination: NoteEditor(id: note.id) // ભҠޙͷը໘ ) } } SwiftUI Navigation ͷ၆ᛌ > OS ʹΑΔมԽ͕ܹ͍͠ Navigation -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
Navigation API େ͖͘ 2 ͭʹྨͰ͖Δ • Fire and forget Navigation
API • State driven Navigation API 36 SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API -
Fire and forget Navigation API • Binding ҾΛऔΒͳ͍ • SwiftUI
͕ Navigation ͷঢ়ଶΛશʹ෦Ͱཧ͢Δ • Navigation Λૉૣ࣮͘ݱͰ͖Δ͕ɺNavigation ʹରͯ͠ ϓϩάϥϜతͳ੍ޚ͕Ͱ͖ͳ͘ͳΔ 37 SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API -
Fire and forget API - Tab - TabView { ReceivedView()
.tabItem { // ... } SentView() .tabItem { // ... } AccountView() .tabItem { // ... } } SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API -
Fire and forget API - Tab - // Binding ҾΛऔΒͳ͍ɻλοϓͰ͔͠
navigation Ͱ͖ͳ͍ TabView { ReceivedView() .tabItem { // ... } SentView() .tabItem { // ... } AccountView() .tabItem { // ... } } SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API -
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 -
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 -
Navigation API େ͖͘ 2 ͭʹྨͰ͖Δ • Fire and forget Navigation
API • State driven Navigation API 42 SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API -
State driven Navigation API • Binding ҾΛऔΔ • Navigation Λ༗ޮɾແޮʹ͢Δ࣌ʹυϝΠϯͷঢ়ଶมߋͰ͖Δ
• Fire and forget API ΑΓෳࡶͰ͋Δ͕ɺϓϩάϥϜతͳ੍ޚ͕ ՄೳͱͳΔͨΊɺ͍ํʹΑͬͯ Deep Link ͳͲ࣮ݱͰ͖Δ 43 SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API -
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 -
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 -
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 -
ҟͳΔ View ͰแΉͱ Deep Link Ͱ͖ͳ͍ struct ContainerView: View {
var body: some View { ContentView(selectedTab: .received) } } SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API -
ContainerView ʹঢ়ଶΛ࣋ͨͤͯղܾ͢Δʁ struct ContainerView: View { let selectedTab: Tab var
body: some View { ContentView(selectedTab: selectedTab) } } SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API -
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 -
ΞϓϦͷঢ়ଶΛཧ͢Δ ViewModel Λಋೖ͠ ղܾ͢Δ class AppViewModel: ObservableObject { @Published
var selectedTab: Tab init(selectedTab: Tab = .received) { self.selectedTab = selectedTab } } SwiftUI Navigation ͷ၆ᛌ > Fire and forget / State driven Navigation API -
ΞϓϦͷঢ়ଶΛཧ͢Δ 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 -
Navigation API ʹ͓͚Δ՝ 1. ભҠઌͷը໘ʹ Binding value Λ͢ػߏΛඋ͍͑ͯͳ͍ 2. ঢ়ଶཧΛෳࡶʹͤ͞Δ
API ͕ଘࡏ͍ͯ͠Δ 3. ෳͷ Navigation Λཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ SwiftUI ͷ Navigation API ʹ͓͚Δ՝ -
Navigation API ʹ͓͚Δ՝ 1. ભҠઌͷը໘ʹ Binding value Λ͢ػߏΛඋ͍͑ͯͳ͍ 2. ঢ়ଶཧΛෳࡶʹͤ͞Δ
API ͕ଘࡏ͍ͯ͠Δ 3. ෳͷ Navigation Λཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ SwiftUI ͷ Navigation API ʹ͓͚Δ՝ > ભҠઌͷը໘ʹ Binding value Λ͢ػߏΛඋ͍͑ͯͳ͍ -
ભҠઌͷը໘ʹ 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 Λ͢ػߏΛඋ͍͑ͯͳ͍ -
ભҠઌͷը໘ʹ 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 Λ͢ػߏΛඋ͍͑ͯͳ͍ -
ભҠઌͷը໘ʹ 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 ʹө͞Εͳ͍ -
Navigation API ʹ͓͚Δ՝ 1. ભҠઌͷը໘ʹ Binding value Λ͢ػߏΛඋ͍͑ͯͳ͍ 2. ঢ়ଶཧΛෳࡶʹͤ͞Δ
API ͕ଘࡏ͍ͯ͠Δ 3. ෳͷ Navigation Λཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ SwiftUI ͷ Navigation API ʹ͓͚Δ՝ > ঢ়ଶཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ -
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 ͕ଘࡏ͍ͯ͠Δ -
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 ͕ଘࡏ͍ͯ͠Δ -
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 ͕ଘࡏ͍ͯ͠Δ -
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 ͕ଘࡏ͍ͯ͠Δ -
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 ͕ଘࡏ͍ͯ͠Δ -
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 ͕ଘࡏ͍ͯ͠Δ -
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 ͕ଘࡏ͍ͯ͠Δ -
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 ͕ଘࡏ͍ͯ͠Δ -
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 ͕ଘࡏ͍ͯ͠Δ -
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 -
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 -
New boolean binding and optional item API ঢ়ଶཧΛෳࡶʹͤͯ͞͠·͏
• ։ൃऀ͕ҎԼͷঢ়ଶͷ߹ੑΛؾʹ͠ͳ͚Ε͍͚ͳ͍ͷ͕ਏ͍ • Alert Λදࣔ͢ΔͨΊͷ boolean binding • Alert ͷ༰Λ࡞ΔͨΊͷ optional item • Navigation ͕γϯϓϧͳ͏ͪͦ͜·ͰࠔΒͳ͍͔͠Εͳ͍͕ɺ Navigation ͕૿͑Ε༰қʹঢ়ଶཧෳࡶʹͳͬͯ͠·͏ SwiftUI ͷ Navigation API ʹ͓͚Δ՝ > ঢ়ଶཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ -
Navigation API ʹ͓͚Δ՝ 1. ભҠઌͷը໘ʹ Binding value Λ͢ػߏΛඋ͍͑ͯͳ͍ 2. ঢ়ଶཧΛෳࡶʹͤ͞Δ
API ͕ଘࡏ͍ͯ͠Δ 3. ෳͷ Navigation Λཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ SwiftUI ͷ Navigation API ʹ͓͚Δ՝ > ෳͷ Navigation Λཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ -
ෳͷ 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 Λཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ -
ෳͷ 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 Λཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ -
ෳͷ 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 Λཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ -
༷ʑͳύλʔϯͷঢ়ଶ͕ൃੜͯ͠͠·͏ %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 Λཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ -
༷ʑͳύλʔϯͷঢ়ଶ͕ൃੜͯ͠͠·͏ %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 Λཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ -
Navigation API ʹ͓͚Δ՝ 1. ભҠઌͷը໘ʹ Binding value Λ͢ػߏΛඋ͍͑ͯͳ͍ 2. ঢ়ଶཧΛෳࡶʹͤ͞Δ
API ͕ଘࡏ͍ͯ͠Δ 3. ෳͷ Navigation Λཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ Navigation API ͷ՝ʹͲ͏ཱ͔ͪ͏͔ -
ʮswiftui-navigation ʯͷΞϓϩʔν 1. ભҠઌͷը໘ʹ Binding value Λ͢ػߏΛඋ͍͑ͯͳ͍ • Binding value
Λ͢͜ͱ͕Ͱ͖Δ API overloads 2. ঢ়ଶཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ • ࠷ݶͷঢ়ଶͷΈΛཁٻ͢Δ API overloads 3. ෳͷ Navigation Λཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ • Navigation Λ enum ͰཧͰ͖ΔΑ͏ʹ͢Δ API overloads Navigation API ͷ՝ʹͲ͏ཱ͔ͪ͏͔ -
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 ͷ՝ʹͲ͏ཱ͔ͪ͏͔ -
ʮswiftui-navigation ʯͷΞϓϩʔν 1. ભҠઌͷը໘ʹ Binding value Λ͢ػߏΛඋ͍͑ͯͳ͍ • Binding value
Λ͢͜ͱ͕Ͱ͖Δ API overloads 2. ঢ়ଶཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ • ࠷ݶͷঢ়ଶͷΈΛཁٻ͢Δ API overloads 3. ෳͷ Navigation Λཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ • Navigation Λ enum ͰཧͰ͖ΔΑ͏ʹ͢Δ API overloads Navigation API ͷ՝ʹͲ͏ཱ͔ͪ͏͔ -
ʮ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 -
ભҠઌͷը໘ʹ 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 Λ͢ػߏΛ උ͍͑ͯͳ͍ 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 ʹө͞Εͳ͍ -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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<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<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 -
࡞ͨ͠ 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 -
࡞ͨ͠ 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 -
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 -
ʮswiftui-navigation ʯͷΞϓϩʔν 1. ભҠઌͷը໘ʹ Binding value Λ͢ػߏΛඋ͍͑ͯͳ͍ • Binding value
Λ͢͜ͱ͕Ͱ͖Δ API overloads 2. ঢ়ଶཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ • ࠷ݶͷঢ়ଶͷΈΛཁٻ͢Δ API overloads 3. ෳͷ Navigation Λཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ • Navigation Λ enum ͰཧͰ͖ΔΑ͏ʹ͢Δ API overloads Navigation API ͷ՝ʹͲ͏ཱ͔ͪ͏͔ > ঢ়ଶཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ > ࠷ݶͷঢ়ଶͷΈΛཁٻ͢Δ API overloads -
ঢ়ଶཧΛෳࡶʹͤ͞Δ 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 -
ঢ়ଶཧΛෳࡶʹͤ͞Δ 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 -
ঢ়ଶཧΛෳࡶʹͤ͞Δ 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 -
ͳͥঢ়ଶཧΛෳࡶʹ͢Δ 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 -
ঢ়ଶཧΛෳࡶʹͤ͞ͳ͍ 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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
࡞ͨ͠ 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 -
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 -
ʮ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 -
ෳͷ 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 -
༷ʑͳύλʔϯͷঢ়ଶ͕ൃੜͯ͠͠·͏ %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 -
༷ʑͳύλʔϯͷঢ়ଶ͕ൃੜͯ͠͠·͏ %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 -
ෳͷ Navigation ͷ࠷దͳϞσϦϯάΛߟ͑Δ // Navigation ಉ࣌ʹෳൃੜ͢Δ͜ͱ͕ͳ͍ͨΊɺͬͱྑ͍ϞσϦϯά͕Ͱ͖ͦ͏ @State var draft: Post?
@State var settings: Settings? @State var userProfile: Profile? Navigation API ͷ՝ʹͲ͏ཱ͔ͪ͏͔ > ෳͷ Navigation Λཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ > Navigation Λ enum ͰཧͰ͖ΔΑ͏ʹ͢Δ API overloads -
ෳͷ 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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 ͷ ຒΊࠐΈʯΛ͍ͨ͠༻్Ͱར༻͍ͯ͠Δ -
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 -
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 -
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 -
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 -
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 Ͱѻ͍͍͢ 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?> Λநग़͢Δ -
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?> Λநग़͢Δ -
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?> Λநग़͢Δ -
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 Ͱѻ͍͍͢ 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 Ͱѻ͍͍͢ 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?> -
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 -
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 -
Navigation API ͷվળʹΑΔޮՌ • SwiftUI ͷ Navigation API ʹ͓͚Δ ՝Λ
API overloads ͱ͍͏ γϯϓϧͳํ๏ͰղܾͰ͖ͨ (ϥΠϒϥϦͷ࣮ͬͱચ࿅͞Ε͍ͯ·͢) 1. ભҠઌͷը໘ʹ Binding value Λ͢ػߏΛඋ͍͑ͯͳ͍ 2. ঢ়ଶཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ 3. ෳͷ Navigation Λཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ • Navigation API ͕ΑΓ҆શͰѻ͍͘͢ͳΓɺNavigation ʹؔΘΔঢ়ଶͷཧ ༰қʹͳΔ Navigation API ͷ՝ʹͲ͏ཱ͔ͪ͏͔ -
·ͱΊ • SwiftUI ʹ༷ʑͳ Navigation API ͕͋ΓɺOS ͱڞʹܹ͍͠มԽ͕ ͋ͬͨ •
େ͖͘ Navigation API ҎԼͷ 2 छྨʹ۠ผͰ͖Δ • Fire and forget API • State driven API -
·ͱΊ • SwiftUI ͷ Navigation API ʹҎԼͷΑ͏ͳ՝͕͋ΓɺAPI Λదʹ overload ͯ͠ղܾ͢Δ
ʮswiftui-navigationʯͷΑ͏ͳΞϓϩʔνଘࡏ͍ͯ͠Δ • ભҠઌͷը໘ʹ Binding value Λ͢ػߏΛඋ͍͑ͯͳ͍ • ঢ়ଶཧΛෳࡶʹͤ͞Δ API ͕ଘࡏ͍ͯ͠Δ • ෳͷ Navigation Λཧͩ͢͠ͱແବͳঢ়ଶ͕૿͑Δ • SwiftUI ͷ Navigation Λਖ਼͘͠ཧղͯ͠ཧ͢Ε৭ʑͳԸܙ͕͋Δ • Navigation ʹؔΘΔঢ়ଶཧʹ·͞Εͳ͍ • Deep Link ͕༰қʹͳΔɾXcode Previews ׆༻͘͢͠ͳΔ -
ࢀߟ • 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/