QDRouter.swift
import SwiftUI@MainActor
class QDRouter: ObservableObject {@Published var path = NavigationPath()static let main = QDRouter() // 单例private init() {}func open(_ url: String) {guard let url = URL(string: url) else {return}UIApplication.shared.open(url)}func push(page: RoutePage, param: [String: String]? = nil) {path.append(QDRoute(page: page, param: param))}func pop() {path.removeLast()}func popToRoot() {path.removeLast(path.count)}
}// MARK: route pageenum RoutePage {case nonecase centercase web
}struct QDRoute: Hashable {var page: RoutePagevar param: [String: String]?
}// MARK: present viewenum PresentPage {case nonecase web
}class PresentObject: ObservableObject {@Published var pageName: PresentPage = .none@Published var isPresent: Bool = false@Published var param: [String: String]?func presentView(pageName: PresentPage, param: [String: String]? = nil, isPresent: Bool = true) {self.pageName = pageNameself.param = paramself.isPresent = isPresent}
}extension View {func withNavDestination() -> some View {return navigationDestination(for: QDRoute.self) { route inlet param = route.paramswitch route.page {case .center:CenterView(param: param)case .none:Text("")case .web:WebView()}}}func withPresentDestination(isPresent: Binding<Bool>, pageName: PresentPage, param: [String: String]?) -> some View {return fullScreenCover(isPresented: isPresent, onDismiss: {print("")}, content: {switch pageName {case .web:WebView(param: param)case .none:Text("")}})}
}
初始页面:
LaunchView.swift
import SwiftUI/// 启动视图
struct LaunchView: View {@State private var logoOpacity: Double = 0.0@State var isPreview = false@StateObject var router = QDRouter.main@State var showCenter = false@StateObject private var presentObject = PresentObject()var body: some View {NavigationStack(path: $router.path) {VStack {if showCenter {CenterView()} else {ZStack(alignment: Alignment.bottom, content: {ZStack {Image("startImageNew").resizable().edgesIgnoringSafeArea(.all)Image("launchTopLogo").opacity(logoOpacity)}Image("launchBottomLogo")}).onAppear {let duration = 0.5withAnimation(.easeIn(duration: duration)) {logoOpacity = 1.0}DispatchQueue.main.asyncAfter(deadline: .now() + duration) {print("动画完成")if !isPreview {self.showCenter = true}}}}}.withNavDestination()}.environmentObject(presentObject)}
}struct LaunchView_Previews: PreviewProvider {static var previews: some View {LaunchView(isPreview: true)}
}
由 LaunchView跳转到CenterView
CenterView.swift
import SwiftUIstruct CenterView: View {@State private var selectedTab = 0@EnvironmentObject var presentObject: PresentObjectvar param: [String: String]?var body: some View {TabView(selection: $selectedTab) {FirstView().tabItem {(selectedTab == 0) ? Image(systemName: "house.fill") : Image(systemName: "house")Text("首页")}.tag(0)SecondView().tabItem {Image(systemName: "dollarsign.circle")Text("财富")}.tag(1)ThirdView().tabItem {Image(systemName: "wallet.pass")Text("钱包")}.tag(2)FourthView().tabItem {Image(systemName: "person")Text("个人")}.tag(3)}.navigationBarBackButtonHidden(true).onAppear {}.withPresentDestination(isPresent: $presentObject.isPresent, pageName: presentObject.pageName, param: presentObject.param)}
}#Preview {CenterView(param: [:])
}
withNavDestination 用于控制路由的push和pop
withPresentDestination 用于控制present view
具体使用:
@EnvironmentObject var presentObject: PresentObjectvar body: some View {VStack {Text("Hello, World 4")Button("present view") {presentObject.presentView(pageName: .web)}Button("push view") {QDRouter.main.push(page:.web)}}}