因为对moya框架的使用,给了我启发,花点时间封装了下 NavigationStack 的路由管理。不多说,上代码:
先定义个Path的枚举,对应APP的每个页面,可带参数(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)//带参数类型测试
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 协议代理,协议方法 有push...等这些一看就懂。
protocol SFNavigationDelegate{
associatedtype Route = SFNavigationPath
func push(_ path:Route)
func pop()
func popToRoot()
func popUntil(_ path:Route)
}
继续做一个View分类用来 导航页面用,具体就是用到的时候,需要实现调用,当然也可以自己实现navigationDestination,具体看业务需求吧。
extension View{
//返回默认,或者简单参数的页面
func pathNormalPageView() -> some View {
self.navigationDestination(for: SFNavigationPath.self) { path in
path.pageParamView()
}
}
//如果复杂参数,可以用这个
func pathCustPageView(@ViewBuilder destination: @escaping (_ path:SFNavigationPath) -> some View) -> some View{
self.navigationDestination(for: SFNavigationPath.self, destination: destination)
}
}
最后写一个manger 遵守协议来管理导航
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{//刷新消息数量
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)
}
如果带参数可以这样用:
pathManger.push(.testPath(100))
如果是复杂参数可以这样用:
.pathCustPageView { path in
if path == .testPath2{
//TODO
}
}