You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS15+ SwiftUI Coordinator导航异常问题求助

iOS15+ SwiftUI导航栈Coordinator跳转异常修复方案

问题原因

你当前的代码使用单个selection变量控制所有NavigationLink,导致跳转到第三个视图时,根视图的NavigationLink因selection值不再匹配自身tag,触发自动dismiss,直接回到根页面。

因为NavigationLink的tag-selection机制是:当selection等于tag时激活跳转;当selection不等于tag时,若已跳转则自动关闭该链路,这就导致了跨层级跳转时的栈重置问题。

修复方案

改用导航路径数组管理导航状态,让每个NavigationLink独立控制自身的激活状态,避免全局变量冲突。这种方案完全兼容iOS15,同时具备良好的扩展性。

修改后的完整代码

import SwiftUI
import Combine

final class FlowCoordinator: ObservableObject {
    // 用数组维护导航路径,记录当前栈中的页面tag
    @Published var navigationPath: [String] = []
    
    private var cancellables = Set<AnyCancellable>()

    init() {
        addObserver()
    }
    
    // 推入新页面
    func push(_ viewTag: String) {
        navigationPath.append(viewTag)
    }
    
    // 返回上一页
    func pop() {
        if !navigationPath.isEmpty {
            navigationPath.removeLast()
        }
    }
    
    // 返回根页面
    func popToRoot() {
        navigationPath.removeAll()
    }
    
    private func addObserver() {
        $navigationPath
            .sink { path in
                print("当前导航路径: \(path)")
            }
            .store(in: &cancellables)
    }
}

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时激活
                isActive: .init(
                    get: { coordinator.navigationPath.contains("MealDetailsScreen") },
                    set: { newValue in
                        // 返回时从路径中移除对应tag
                        if !newValue {
                            coordinator.pop()
                        }
                    }
                )
            ) {
                EmptyView()
            }

            Button(action: {
                coordinator.push("MealDetailsScreen")
            }) {
                Text("Go to Meal Details")
            }
        }
    }
}

struct MealDetailsScreen: View {
    @EnvironmentObject var coordinator: FlowCoordinator

    var body: some View {
        VStack {
            NavigationLink(
                destination: MealMultimediaScreen(),
                isActive: .init(
                    get: { coordinator.navigationPath.contains("MealMultimediaScreen") },
                    set: { newValue in
                        if !newValue {
                            coordinator.pop()
                        }
                    }
                )
            ) {
                EmptyView()
            }

            Button(action: {
                coordinator.push("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"),
                isActive: .init(
                    get: { coordinator.navigationPath.contains("Text") },
                    set: { newValue in
                        if !newValue {
                            coordinator.pop()
                        }
                    }
                )
            ) {
                EmptyView()
            }

            Button(action: {
                coordinator.push("Text")
            }) {
                Text("Go to Text")
            }
        }
        .navigationTitle("Meal Multimedia")
    }
}

#Preview {
    ContentView()
}

关键改动说明

  1. Coordinator状态管理:用navigationPath数组替代单个selection变量,记录所有已推入的页面tag,清晰维护导航栈层级。
  2. NavigationLink激活逻辑:每个NavigationLink通过isActive绑定到路径是否包含自身目标tag,避免全局变量冲突。
  3. 返回逻辑联动:当用户通过系统返回按钮返回时,自动调用pop()方法更新路径数组,保持状态与UI一致。

内容的提问来源于stack exchange,提问作者Andres Paladines

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 19:29:51