В NavigationStack отсутствует корневой контроллер из пути
я создаю историческую навигацию (назад, вперед) для приложения macOS
В основном это работает нормально, но моя реализация зависит от пути, который, однако, не содержит корня (когда выбрана боковая панель, а [] назначается пути)
как получить рут, или сохранить рут отnavigationDestination
import SwiftUI
enum NavigationDestination: Hashable {
case test1
case test2
case test3(text:String)
}
struct SidebarView: View {
var body: some View {
VStack {
NavigationLink(value: NavigationDestination.test1) {
Text("1")
}
NavigationLink(value: NavigationDestination.test2) {
Text("2")
}
NavigationLink(value: NavigationDestination.test3(text:"X")) {
Text("3")
}
}
}
}
struct TestView: View {
let text: String
var body: some View {
VStack {
Text(text)
NavigationLink(value: NavigationDestination.test1) {
Text("1")
}
NavigationLink(value: NavigationDestination.test2) {
Text("2")
}
NavigationLink(value: NavigationDestination.test3(text:"3-1")) {
Text("3-1")
}
NavigationLink(value: NavigationDestination.test3(text:"3-2")) {
Text("3-2")
}
NavigationLink(value: NavigationDestination.test3(text:"3-3")) {
Text("3-3")
}
NavigationLink(value: NavigationDestination.test3(text:"3-4")) {
Text("3-4")
}
NavigationLink(value: NavigationDestination.test3(text:"3-5")) {
Text("3-5")
}
List {
ForEach(0..<200) { index in
Text("LIST \(index)")
}
}
}
}
}
struct MainView: View {
@State private var history: [[NavigationDestination]] = []
@State private var historyIndex: Int = -1
@State private var canGoBackInHistory = false
@State private var canGoForwardInHistory = false
@State private var path: [NavigationDestination] = []
var body: some View {
NavigationSplitView(columnVisibility: .constant(.all)) {
SidebarView()
.navigationDestination(for: NavigationDestination.self) { destination in
detailBuilder(destination)
.navigationBarBackButtonHidden(true)
}
} detail: {
NavigationStack(path: $path) {
Group {
}
.navigationDestination(for: NavigationDestination.self) { destination in
detailBuilder(destination)
.navigationBarBackButtonHidden(true)
}
}
}
.onChange(of: path) { newValue in
if history[safe: historyIndex] == newValue {
return
}
if historyIndex != history.count - 1 {
history.removeLast(history.count - historyIndex)
}
if newValue != [] {
history.append(newValue)
}
historyIndex = history.count - 1
canGoBackInHistory = history.count > 0
canGoForwardInHistory = false
print("======\n \(history)")
}
.toolbar {
ToolbarItemGroup(placement: .navigation) {
Button(action: {
goBackInHistory()
}, label: {
Image(systemName: "chevron.left")
})
.disabled(!canGoBackInHistory)
Button(action: {
goForwardInHistory()
}, label: {
Image(systemName: "chevron.right")
})
.disabled(!canGoForwardInHistory)
}
}
}
func goBackInHistory() {
guard let h = history[safe: historyIndex - 1] else {
return
}
historyIndex -= 1
canGoBackInHistory = historyIndex > 0
canGoForwardInHistory = true
withAnimation {
path = h
}
}
func goForwardInHistory() {
guard let h = history[safe: historyIndex + 1] else {
return
}
historyIndex += 1
canGoBackInHistory = true
canGoForwardInHistory = historyIndex < (history.count - 1)
withAnimation {
path = h
}
}
@ViewBuilder
func detailBuilder(_ destination: NavigationDestination) -> some View {
switch destination {
case .test1:
TestView(text: "1")
case .test2:
TestView(text: "2")
case .test3(let text):
TestView(text: text)
}
}
}
struct MainView_Previews: PreviewProvider {
static var previews: some View {
MainView()
}
}
extension Collection where Indices.Iterator.Element == Index {
/// Returns the element at the specified index if it is within bounds, otherwise nil.
subscript (safe index: Index) -> Iterator.Element? {
return indices.contains(index) ? self[index] : nil
}
}