我正在尝试创建一种协调器,在导航时堆叠视图并使其与 iOS 15.0 兼容。 这是我的代码,适用于第一次推送到下一个视图,但进入第三个视图后,它返回到第一个视图...... 我愿意接受任何建议,但我必须保持 iOS15 的兼容性。 这是我的代码:
import SwiftUI
import Combine
final class FlowCoordinator: ObservableObject {
@Published var selection: String?
private var cancellables = Set<AnyCancellable>()
init() {
addOberver()
}
func showView(_ view: String) {
selection = view
}
func addOberver() {
$selection
.sink { newString in
print(newString ?? "")
}
.store(in: &cancellables)
}
func repeatPrints() {
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { timer in
print(self.selection ?? "")
}
}
}
struct ContentView: View {
@StateObject var coordinator = FlowCoordinator()
var body: some View {
NavigationView {
MainListScreen()
.navigationTitle("Main List")
}
.environmentObject(coordinator)
.navigationViewStyle(StackNavigationViewStyle())
}
}
struct MainListScreen: View {
@EnvironmentObject var coordinator: FlowCoordinator
var body: some View {
VStack {
NavigationLink(destination: MealDetailsScreen(),
tag: "MealDetailsScreen",
selection: $coordinator.selection) {
EmptyView()
}
Button(action: {
coordinator.showView("MealDetailsScreen")
}) {
Text("Go to Meal Details")
}
}
}
}
struct MealDetailsScreen: View {
@EnvironmentObject var coordinator: FlowCoordinator
var body: some View {
VStack {
NavigationLink(destination: MealMultimediaScreen(),
tag: "MealMultimediaScreen",
selection: $coordinator.selection) {
EmptyView()
}
Button(action: {
coordinator.showView("MealMultimediaScreen")
}) {
Text("Go to Meal Multimedia")
}
}
.navigationTitle("Meal Details")
}
}
struct MealMultimediaScreen: View {
@EnvironmentObject var coordinator: FlowCoordinator
var body: some View {
VStack {
NavigationLink(destination: Text("Last View"),
tag: "Text",
selection: $coordinator.selection) {
EmptyView()
}
Button(action: {
coordinator.showView("Text")
}) {
Text("Go to Text")
}
}
.navigationTitle("Meal Multimedia")
}
}
#Preview {
ContentView()
}
当您推送第三个视图时,
coordinator.selection
会更新为 MealMultimediaScreen
,这与第一个链接的标签 MealDetailsScreen
不匹配并弹出视图。
这种带有标签和选择的导航方法仅适用于单个视图,因为一个视图无法同时导航到多个目的地,并且它需要您为每个目的地都有一个单独的
FlowCoordinator
View
。
我建议您使用
NavigationLink(isActive:
,因为您可以基于堆栈操作 isActive
参数:
final class FlowCoordinator: ObservableObject {
@Published var stack = [String]()
private var cancellables = Set<AnyCancellable>()
private func pop(to tag: String) {
var lastTag: String?
while lastTag != tag {
lastTag = stack.popLast()
}
}
func isActive(for tag: String) -> Binding<Bool> {
return Binding {
return self.stack.contains(tag)
} set: { newValue in
if !newValue {
self.pop(to: tag)
}else {
self.stack.append(tag)
}
}
}
func push(_ tag: String) {
stack.append(tag)
}
func pop() {
_ = stack.popLast()
}
}
然后创建一个处理协调器的
NavigationLink
包装器:
struct NavigationLinkView<Content: View>: View {
@EnvironmentObject private var coordinator: FlowCoordinator
private let destination: Content
private let tag: String
init(tag: String, destination: Content) {
self.destination = destination
self.tag = tag
}
var body: some View {
NavigationLink(isActive: coordinator.isActive(for: tag)) {
destination
} label: {
EmptyView()
}
}
}
用途:
NavigationLink(tag: "MealDetailsScreen", destination: MealDetailsScreen())