SwiftUI:NavigationStack编程式添加不同类型子视图的问题
问题场景与代码实现
父视图代码
struct MainDatabaseView: View { @State private var path = NavigationPath() var body: some View { NavigationStack(path: $path) { List { Section { NavigationLink(destination: MainTabPilotDatabaseView(path: $path)) { Label("Pilots", systemImage: "person.2") .foregroundStyle(.primary) } NavigationLink(destination: MainTabAircraftDatabaseView()) { Label("Aircraft", systemImage: "airplane.circle") .foregroundStyle(.primary) } } header: { Text("Database") } } } }
子视图代码
struct MainTabPilotDatabaseView: View { @EnvironmentObject var pilotVM: PilotVM @Binding var path : NavigationPath var body: some View { List { ForEach(pilotVM.filteredPilots, id: \.id) { pilot in NavigationLink { PilotDatabaseDetailView(pilot: pilot) } label: { PilotCell(pilot: pilot, isInDetailView: false) .contentShape(Rectangle()) .swipeActions(edge: .trailing) { delete(for: pilot) } .swipeActions(edge: .leading) { markFavorite(for: pilot) } } } } .toolbar { ToolbarItem(placement: .topBarTrailing) { addPilot() } } } func addPilot() -> some View { Button { let pilotModelInput = PilotModelInput() let new = pilotVM.addPilotToModel(input: pilotModelInput) path.append(new) } label: { Image(systemName: "plus.circle.fill") } } }
问题描述
当path定义为@State var path: [PilotEntity] = []时,点击子视图中的“plus.circle.fill”按钮可正常在NavigationStack中推入子子视图。但由于需要在NavigationStack中同时支持AircraftEntity类型,必须改用通用的NavigationPath,改用后无法将数据传递到子子视图,寻求最佳解决方式。
可行解决方案(编辑补充)
通过以下方式实现后可解决问题:
import SwiftUI enum DatabaseTabOption { case pilot, aircraft } class NavigationStackManager: ObservableObject { @Published var path = NavigationPath() } struct MainDatabaseView: View { @StateObject var pathManager = NavigationStackManager() var body: some View { NavigationStack(path: $pathManager.path) { List { Section { NavigationLink(value: DatabaseTabOption.pilot) { Button { pathManager.path.append(DatabaseTabOption.pilot) } label: { Label("Pilots", systemImage: "person.2") } } NavigationLink(value: DatabaseTabOption.aircraft) { Button { pathManager.path.append(DatabaseTabOption.aircraft) } label: { Label("Aircraft", systemImage: "airplane.circle") } } } header: { Text("Database") } } .navigationDestination(for: DatabaseTabOption.self, destination: { value in switch value { case .pilot: MainTabPilotDatabaseView() .environmentObject(pathManager) case .aircraft: MainTabAircraftDatabaseView() .environmentObject(pathManager) } }) } } }
实现思路:
- 定义枚举
DatabaseTabOption作为导航的标识类型 - 创建
NavigationStackManager类统一管理NavigationPath,通过@Published发布路径变化 - 父视图中使用
NavigationLink(value:)结合navigationDestination(for:destination:)关联导航目标 - 将
Button包裹在NavigationLink中保留导航箭头提示 - 通过
environmentObject将路径管理器传递给子视图,子视图即可向path添加任意类型的数据
内容的提问来源于stack exchange,提问作者Petr Smejkal
相关产品推荐
相关产品推荐

