至少有两种方法可以实现你想要的:
- 使用
.id()
API重置NavigationLink
.
enum TabSelection {
case first
case second
}
private final class ContentViewModel: ObservableObject {
@Published var tabSelection = TabSelection.first
}
struct ContentView: View {
@StateObject private var viewModel = ContentViewModel()
@State private var tab0Id = UUID()
var body: some View {
TabView(selection: $viewModel.tabSelection) {
NavigationView {
VStack {
Text("View1")
NavigationLink {
Text("Child View")
} label: {
Text("Go to child view")
}
.id(tab0Id)
}
}
.tag(TabSelection.first)
.tabItem {
Label("view1", systemImage: "1.circle")
}
Text("View2")
.tabItem {
Label("view2", systemImage: "2.circle")
}
.tag(TabSelection.second)
}
.onReceive(viewModel.$tabSelection) { newValue in
if newValue == .first {
tab0Id = UUID()
}
}
}
}
结果是:
- 将视图模型作为
EnvironmentObject
注入子视图中:
enum TabSelection {
case first
case second
}
private final class ContentViewModel: ObservableObject {
@Published var tabSelection = TabSelection.first
}
struct ContentView: View {
@StateObject private var viewModel = ContentViewModel()
var body: some View {
TabView(selection: $viewModel.tabSelection) {
NavigationView {
VStack {
Text("View1")
NavigationLink {
ChildView()
} label: {
Text("Go to child view")
}
}
}
.tag(TabSelection.first)
.tabItem {
Label("view1", systemImage: "1.circle")
}
Text("View2")
.tabItem {
Label("view2", systemImage: "2.circle")
}
.tag(TabSelection.second)
}
.environmentObject(viewModel)
}
}
struct ChildView: View {
@Environment(\.dismiss) private var dismiss: DismissAction
@EnvironmentObject private var rootViewModel: ContentViewModel
var body: some View {
Text("Child View")
.onReceive(rootViewModel.$tabSelection) { newValue in
if newValue == .first {
dismiss()
}
}
}
}
结果是:
EDIT:附注:如果仅当您在第一个选项卡上并点击第一个选项卡项时才需要重置导航,您只需更改onReceive
中的逻辑如下:
.onReceive(viewModel.$tabSelection) { [oldValue = viewModel.tabSelection] newValue in
if oldValue == .first && newValue == .first {
tab0Id = UUID() // or `dismiss()` if you prefer the second way I described here above
}
}
结果是: