У меня есть приложение, которое я запущу на iPad. Я настраиваю боковую панель, но застрял. Я хочу иметь возможность выбрать страницу, а затем переходить внутри этой выбранной страницы на другие страницы.
В данный момент происходит следующее: я прекрасно выбираю страницы на боковой панели, а затем в основном представлении. Если я нажимаю кнопку, которая перемещает меня от этого основного представления к другому, боковая панель становится бесполезной. Мне нужно нажать «Назад», чтобы вернуться к исходному виду, выбранному на боковой панели, и тогда боковая панель снова станет активной.
В примере приложения - если вы перейдете к «wx по прибытии» на боковой панели, а затем нажмите кнопку «Перейти к настройкам» на «второй уровень», боковая панель не будет работать...
Я хочу, чтобы это произошло: независимо от того, насколько глубоко я углубляюсь в одно выбранное представление боковой панели, я хочу иметь возможность выбрать любой из параметров боковой панели и сразу перейти к тому, к чему я пытаюсь перейти. Спасибо.
Вот очень простая воспроизводимая версия проблемы, прошу прощения за много страниц:
import SwiftUI
@main
struct scrapAppApp: App {
var body: some Scene {
WindowGroup {
MenuView()
}
}
}
funcs.swift
class AppState: ObservableObject {
@Published var destination: String = ""
@Published var path = NavigationPath()
@Published var selectedItem: SidebarItem?
@Published var readyToNavigate : Bool = false
}
МенюView.swift
enum SidebarItem: String, Identifiable, CaseIterable {
case initialScreen = "Initial Screen"
case arrivalWx = "Wx On Arrival"
case legal = "Legal"
var id: String { self.rawValue }
var iconName: String {
switch self {
case .initialScreen:
return "house"
case .arrivalWx:
return "cloud.sun"
case .legal:
return "doc.text"
}
}
}
struct MenuView: View {
@StateObject private var app = AppState()
var body: some View {
NavigationSplitView {
List(SidebarItem.allCases, id: \.self, selection: $app.selectedItem) { item in
NavigationLink(value: item) {
Label(item.rawValue, systemImage: item.iconName)
}
}
.listStyle(SidebarListStyle())
.navigationTitle("Menu")
} detail: {
NavigationStack(path: $app.path) {
if let selectedItem = app.selectedItem {
switch selectedItem {
case .initialScreen:
FirstPage()
case .arrivalWx:
SecondPage(app: app)
case .legal:
FourthPage(app: app)
}
} else {
Text("Select an item")
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
}
}
}
FirstPage.swift
struct FirstPage: View {
var body: some View {
Text("INITIAL SCREEN")
}
}
SecondPage.swift
struct SecondPage: View {
@ObservedObject var app: AppState
var body: some View {
Text("WX on ARRIVAL")
Button("Go settings") {
app.readyToNavigate = true
}
.navigationDestination(isPresented: $app.readyToNavigate) {
ThirdPage()
}
}
}
Третья страница.swift
struct ThirdPage: View {
@ObservedObject var app = AppState()
var body: some View {
Text("Second Layer")
}
}
Четвертая страница.swift
struct FourthPage: View {
@ObservedObject var app: AppState
var body: some View {
Button("LEGAL") {
}
}
}
Спасибо @workingdog, поддержите Украину. Сейчас я перешел на EnvironmentObject. Я пробовал в альбомной ориентации, и, похоже, он ведет себя так же, где - после нажатия кнопки «Перейти к настройкам» элементы боковой панели не действуют. Я также заметил, что если на странице «Настройки» нажать «Юридические» на боковой панели, то при нажатии «Назад» отображается страница «Юридическая»… Сбивает с толку.
Я не понимаю никаких твоих проблем. Вы говоритеI want to be able to select a page and then navigate within that selected page to other pages
. Такое поведение я наблюдаю на iPadOS 17.5.1. Кроме того ...the sidebar becomes useless
, я вообще этого не понимаю, боковая панель постоянно реагирует. Я опубликую свой тестовый код.
Вот мой тестовый код, который работает на iPadOS 17.5.1.
struct MenuView: View {
@StateObject private var app = AppState()
var body: some View {
NavigationSplitView {
List(SidebarItem.allCases, selection: $app.selectedItem) { item in
NavigationLink(value: item) {
Label(item.rawValue, systemImage: item.iconName)
}
}
.listStyle(SidebarListStyle())
.navigationTitle("Menu")
} detail: {
NavigationStack(path: $app.path) {
if let selectedItem = app.selectedItem {
switch selectedItem {
case .initialScreen:
FirstPage()
case .arrivalWx:
SecondPage()
case .legal:
FourthPage()
}
} else {
Text("Select an item")
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
.environmentObject(app) // <--- here
}
}
}
class AppState: ObservableObject {
@Published var destination: String = ""
@Published var path = NavigationPath()
@Published var selectedItem: SidebarItem?
@Published var readyToNavigate: Bool = false
}
enum SidebarItem: String, Identifiable, CaseIterable {
case initialScreen = "Initial Screen"
case arrivalWx = "Wx On Arrival"
case legal = "Legal"
var id: String { self.rawValue }
var iconName: String {
switch self {
case .initialScreen:
return "house"
case .arrivalWx:
return "cloud.sun"
case .legal:
return "doc.text"
}
}
}
struct FirstPage: View {
@EnvironmentObject var app: AppState // not used
var body: some View {
Text("FirstPage INITIAL SCREEN")
}
}
struct SecondPage: View {
@EnvironmentObject var app: AppState
var body: some View {
Text("SecondPage WX on ARRIVAL")
Button("Go settings") {
app.readyToNavigate = true
}
.navigationDestination(isPresented: $app.readyToNavigate) {
ThirdPage()
}
}
}
struct ThirdPage: View {
@EnvironmentObject var app: AppState // not used
var body: some View {
Text("ThirdPage Second Layer")
}
}
struct FourthPage: View {
@EnvironmentObject var app: AppState // not used
var body: some View {
Button("FourthPage LEGAL") {
}
}
}
Обратите внимание: я хотел сказать, что в портретном режиме боковая панель исчезает, но в альбомном режиме она остается видимой.
Большое спасибо @workingdog, поддержка Украины. Я скопировал и вставил ваш код дословно. Я получаю то же поведение, что и раньше. Когда я говорю, что это становится бесполезным, я имею в виду, что когда я нахожусь на Третьей странице, на которую перешел с помощью кнопки, нажатие «Начальный экран» или «Юридические вопросы» на боковой панели не приводит к навигации. Мне нужно нажать кнопку «Назад», прежде чем навигация через боковую панель станет видимой. Если это то, что вы получаете и ожидаемое поведение, не беспокойтесь, я поработаю с этим. Спасибо!
Интересно, может ли одновременный жест() сработать для очистки NavigationPath() при нажатии элемента боковой панели? Хотя я не уверен, что это правильный путь.
Как я уже сказал, у меня нет подобных проблем с моим кодом. Когда я нахожусь на третьей странице, на которую перешел с помощью кнопки, нажатие кнопки «Начальный экран» или «Юридические данные» на боковой панели позволяет мне перемещаться. Боковая панель активна. Какую систему вы используете и нацеливаетесь. Сейчас я использую MacOS 15, бета-версию Xcode 16, целевую iOS-17.5, протестирован на реальном (более старом) устройстве iPad и MacCatalyst.
Хорошо, я использовал симулятор, и он не работал. Сейчас я запустил его на настоящем iPad, и он работает хорошо. Я использую MacOS 14.2 Xcode 15 и нацелен на iOS 17 или новее. iPad, над которым он работает, — iOS 17.3. Спасибо за помощь, очень ценю.
Рад, что теперь это работает. Если мой ответ вам помог, примите его, отметив галочку рядом с ним, она станет зеленой.
AFAIK, в iPadOS в портретном режиме это поведение по умолчанию. В ландшафтном режиме вы можете одновременно использовать боковую панель и навигацию. Обратите внимание: поскольку вы используете
AppState
во многих дочерних представлениях, я рекомендую вам использовать.environmentObject(app)
в представлении сверху и в дочерних представлениях@EnvironmentObject var app: AppState
вместо того, чтобы передавать модель повсюду с возможными ошибками, как приThirdPage
повторном объявлении модели.