SwiftUI 路由管理 NavigationStack

因為對moya框架的使用,給了我啟發(fā),花點時間封裝了下 NavigationStack 的路由管理。不多說,上代碼:

先定義個Path的枚舉,對應APP的每個頁面,可帶參數(shù)(moya的API也是這樣處理的)
enum SFNavigationPath:Hashable{
    
    case loginPath
    case baseTabbarPath
    
    case baoBiaoPath
    
    
    case yewuPath
    
    
    case homePath
    
    case customersPath
    case customerDetailPath
    case customerAddOrEidtPath
    
    case newsPath
    case newsDetailPath
    case newsListPath
    
    
    case testPath(_ index:Int)//帶參數(shù)類型測試
    case testPath2
    
    
    func pageParamView() -> some View{
        switch self {
        case .loginPath:
            return AnyView(LoginView())
        case .baseTabbarPath:
            return AnyView(BaseTabbar())
        case .baoBiaoPath:
            return AnyView(BaoBiaoView())
        case .yewuPath:
            return AnyView(YewuView())
        case .homePath:
            return AnyView(HomeSpace())
        case .customersPath:
            return AnyView(CustomersView())
        case .newsPath:
            return AnyView(NewsView())
        case .testPath(let index):
            return AnyView(TestPage(index: index))
        case .testPath2:
            return AnyView(TestPage2())
        default:
            return AnyView(TestPage2())
        }
    }
}

再定義一個SFNavigationDelegate 協(xié)議代理,協(xié)議方法 有push...等這些一看就懂。
protocol SFNavigationDelegate{
    associatedtype Route = SFNavigationPath
    func push(_ path:Route)
    func pop()
    func popToRoot()
    func popUntil(_ path:Route)
}

繼續(xù)做一個View分類用來 導航頁面用,具體就是用到的時候,需要實現(xiàn)調用,當然也可以自己實現(xiàn)navigationDestination,具體看業(yè)務需求吧。
extension View{
    //返回默認,或者簡單參數(shù)的頁面
    func pathNormalPageView() -> some View {
        self.navigationDestination(for: SFNavigationPath.self) { path in
            path.pageParamView()
        }
    }
    
    //如果復雜參數(shù),可以用這個
    func pathCustPageView(@ViewBuilder destination: @escaping (_ path:SFNavigationPath) -> some View) -> some View{
        self.navigationDestination(for: SFNavigationPath.self, destination: destination)
    }
}

最后寫一個manger 遵守協(xié)議來管理導航


class PathManager:ObservableObject,SFNavigationDelegate{
    @Published var manager:[SFNavigationPath] = []
    
    func push(_ path: SFNavigationPath) {
        self.manager.append(path)
    }
    
    func pop() {
        self.manager.removeLast()
    }
    
    func popToRoot() {
        self.manager.removeAll()
    }
    
    func popUntil(_ path: SFNavigationPath) {
        if self.manager.last != path {
            self.manager.removeLast()
            popUntil(path)
        }
    }
    
}

使用方法:pathManager.manager傳入 NavigationStack,然后 注入.environmentObject(pathManager)

@StateObject var pathManager = PathManager()
    var body: some View {
        NavigationStack(path: $pathManager.manager){
            ZStack(alignment: .bottom) {
                TabView(selection: $viewModel.selectedTab) {
                    BaoBiaoView()
                        .tag(SFTabbarType.chartBarType)
                    YewuView()
                        .tag(SFTabbarType.yewuBarType)
                    HomeSpace()
                        .tag(SFTabbarType.homeBarType)
                    CustomersView()
                        .tag(SFTabbarType.custBarType)
                    NewsView()
                        .tag(SFTabbarType.newsBarType)
                }
                .accentColor(.red)
                .background(.red)
                .toast(isPresenting: $viewModel.showMsg, text: viewModel.msg)
                
                SFTabbarView().onAppear{//刷新消息數(shù)量
                    viewModel.getNewsNumber()
                }
            }
            .ignoresSafeArea(.all,edges: .bottom)
            .environmentObject(viewModel)
            .navigationBarTitleDisplayMode(.inline)
        }
        .environmentObject(pathManager)
@EnvironmentObject var pathManger:PathManager
    var body: some View {
        VStack {
            SFNavigationBar(showBackBtn:false,title: "報表"){
                
            }
            BaseListView(viewModel: viewModel) {
                ForEach(viewModel.datas, id: \.self) { item in
                    VStack(spacing: 0){
                        HStack {
                            Text("點擊了\(item)")
                            Text("點擊了\(item)")
                        }
                        .foregroundColor(.black)
                        .padding(.all,15)
                        .frame(minWidth: screenWidth,maxWidth: .infinity)
                        .background(.white)
                        Divider()
                    }
                    .onTapGesture {
                        pathManger.push(.testPath2)
                    }
                }
            }
            .pathNormalPageView()
        }
        .background(viewModel.bgColor)
    }

如果帶參數(shù)可以這樣用:

pathManger.push(.testPath(100))

如果是復雜參數(shù)可以這樣用:

.pathCustPageView { path in
                if path == .testPath2{
                    //TODO
                }
            }
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容