Skip to content

Instantly share code, notes, and snippets.

@timdonnelly
Last active June 5, 2019 17:24
Show Gist options
  • Save timdonnelly/30d19dad32d761463772c04515affc61 to your computer and use it in GitHub Desktop.
Save timdonnelly/30d19dad32d761463772c04515affc61 to your computer and use it in GitHub Desktop.
Controlling navigation with external state in SwiftUI
import SwiftUI
import Combine
enum Destination: Hashable {
case a
case b
case c
}
class NavigationStore: BindableObject {
let didChange = PassthroughSubject<Void, Never>()
var currentDestination: Destination? = nil {
didSet {
didChange.send(())
}
}
}
struct ContentView : View {
var body: some View {
NavigationView {
Root()
}
}
}
struct Root: View {
@ObjectBinding var store: NavigationStore
let link: DynamicNavigationDestinationLink<Destination, Destination, AnyView>
init() {
let store = NavigationStore()
self.store = store
self.link = DynamicNavigationDestinationLink(id: \.self) { destination -> AnyView? in
switch destination {
case .a: return AnyView(A(store: store))
case .b: return AnyView(B(store: store))
case .c: return AnyView(Root())
}
}
}
var body: some View {
if link.presentedData?.value != store.currentDestination {
link.presentedData?.value = store.currentDestination
}
return VStack(spacing: 10) {
Button(action: { self.store.currentDestination = .a }) {
Text("A")
}
Button(action: { self.store.currentDestination = .b }) {
Text("B")
}
Button(action: { self.store.currentDestination = .c }) {
Text("Push another root")
}
}
.navigationBarTitle(Text("Root"))
}
}
struct A: View {
let store: NavigationStore
var body: some View {
VStack {
Button(action: { self.store.currentDestination = nil }) {
Text("Back")
}
}
.navigationBarTitle(Text("A"))
}
}
struct B: View {
let store: NavigationStore
var body: some View {
VStack {
Button(action: { self.store.currentDestination = nil }) {
Text("Back")
}
}
.navigationBarTitle(Text("B"))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment