【iOS】SwiftUI 路由管理(NavigationStack)

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)}}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/74132.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

蓝桥杯学习-13回溯

13回溯 一、回溯1 例题1–递归实现排列型枚举-蓝桥19684 1.递归可以解决不定次数的循环问题 2.使用数组来标记数字是否被选过import java.util.Scanner;public class Main {static int n;static boolean[] st new boolean[10]; //判断数字是否被选过static int[] path ne…

【IDEA中配置Maven国内镜像源】

1. 为什么需要配置国内镜像源&#xff1f; 首先&#xff0c;Maven本身的工作原理是通过从仓库中下载依赖包。而这些依赖通常来自于 Maven中央仓库&#xff08;位于国外&#xff09;&#xff0c;由于网络原因&#xff0c;我们在国内访问这些远程仓库的速度比较慢&#xff0c;甚至…

【QA】观察者模式在QT有哪些应用?

1. 信号与槽机制 Qt的**信号与槽&#xff08;Signals & Slots&#xff09;**是观察者模式的典型实现&#xff0c;通过元对象系统&#xff08;Meta-Object System&#xff09;实现松耦合通信。 核心特点&#xff1a; 类型安全&#xff1a;编译时检查参数匹配跨线程支持&…

uniapp中的路由、本地存储与网络请求

navigator 在UniApp中&#xff0c;navigator 组件用于页面跳转和应用内导航。 基本使用 属性&#xff1a; url: 需要跳转的目标页面路径&#xff0c;路径可以是相对路径或绝对路径。open-type: 跳转的方式&#xff0c;默认为 navigateTo。其他可选值包括&#xff1a;redirec…

python3使用lxml解析xml时踩坑记录

文章目录 你的 XML 数据解析 XML----------------------------1. 获取 mlt 根元素的属性--------------------------------------------------------2. 获取 chain 元素的属性--------------------------------------------------------3. 获取所有 property 的值-------------…

【DeepSeek 学c++】dynamic_cast 原理

用于向下转化。 父类引用指向指类对象 假设父亲是a, 子类是b. B* pb new B; 子类对象 A* pa 父类引用指向子类对象&#xff0c; 那么向上转化 Apa pb 这个是自动完成的&#xff0c;隐式转化&#xff0c;不需要dynamic_cast 向下转化指的是 A pa new B。 这个是指向子类对象…

c++ 数组索引越界检查

用 c 编写了一些程序&#xff0c;发现 c 不会自动检查数组的索引越界问题。有时候程序运行错误&#xff0c;提示的错误信息莫名其妙&#xff0c;但很可能是某个数组越界的问题。 例如&#xff1a; #include <iostream>int main() {double arr[5] {1.1, 2.2, 3.3, 4.4,…

Touch Diver:Weart为XR和机器人遥操作专属设计的触觉反馈动捕手套

在虚拟现实&#xff08;VR&#xff09;和扩展现实&#xff08;XR&#xff09;领域&#xff0c;触觉反馈技术正逐渐成为提升沉浸感和交互体验的重要因素。Weart作为这一领域的创新者&#xff0c;凭借其TouchDIVER Pro和TouchDIVER G1触觉手套&#xff0c;为用户带来了高度逼真的…

基于deepseek的智能语音客服【第二讲】后端异步接口调用封装

本篇内容主要讲前端请求&#xff08;不包含&#xff09;访问后端服务接口&#xff0c;接口通过检索知识库&#xff0c;封装提示词&#xff0c;调用deepseek的&#xff0c;并返回给前端的全过程&#xff0c;非完整代码&#xff0c;不可直接运行。 1.基于servlet封装异步请求 为…

归并排序的思路与实现

归并排序主要是两大模块 分治 和 合并 即将已有序的子序列合并&#xff0c;得到完全有序的序列&#xff1b;即先使每个子序列有序&#xff0c;再使子序列段间有序。若将两个有序表合并成一个有序表&#xff0c;称为二路归并 由于使用了新的数组 那么空间复杂度就为O(n) 但这…

Word中公式自动标号带章节编号

&#xff08;1&#xff09;插入一行三列的表格&#xff0c;设置宽度分别为0.5&#xff0c;13.39和1.5&#xff0c;设置纵向居中&#xff0c;中间列居中对齐&#xff0c;最右侧列靠右对齐&#xff0c;设置段落如下 &#xff08;2&#xff09;插入域代码 【Word】利用域代码快速实…

阿里云服务器环境部署 四 MySQL主从配置

安装MySQL 导入mysql镜像 docker load -i /opt/dockerinstall/mysql/mysql-8.1.0.tar docker run --privilegedtrue --name mysql8 --restartunless-stopped -e MYSQL_ROOT_PASSWORD123456 -p 3306:3306 -v /usr/local/mysql/logs:/var/log/mysql -v /usr/local/mysql/d…

[RH342]iscsi配置与排错

[RH342]iscsi配置与排错 1. 服务端配置1.1 安装targetcli1.2 准备磁盘1.3 服务端配置1.4 防火墙配置 2. 客户端配置2.1 安装客户端软件2.2 配置客户端2.3 连接登录服务端2.4 挂载使用 3. 安全验证扩展3.1 服务端3.2 客户端 4. 常见的排错点4.1 服务端常见错误4.2 客户端常见错误…

服装零售行业数字化时代的业务与IT转型规划P111(111页PPT)(文末有下载方式)

服装零售行业数字化时代的业务与IT转型规划P111 详细资料请看本解读文章的最后内容。 随着数字化技术的迅猛发展&#xff0c;服装零售行业正经历着前所未有的变革。本文将对《服装零售行业数字化时代的业务与IT转型规划P111》进行详细解读&#xff0c;探讨未来几年内该行业的…

基于javaweb的SSM+Maven宠物领养宠物商城流浪动物管理系统与实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论…

PostgreSQL 数据库中导入大量数据

在 PostgreSQL 数据库中导入大量数据,可根据数据来源和格式选择不同的方法。以下为你详细介绍几种常见的方式: 1. 使用 COPY 命令(适用于本地数据文件) COPY 命令是 PostgreSQL 内置的高效数据导入工具,适合处理本地的数据文件。 步骤 准备数据文件 确保你的数据文件格…

C++语法之命名空间二

A.h头文件中代码&#xff1a; namespace a {void 输出(); }; A.cpp源文件中代码&#xff1a; #include <iostream> #include "A.h" void a::输出() {std::cout << "A.h里的输出函数" << std::endl; } B.h头文件中代码&#xff1a; …

基于FPGA的DDS连续FFT 仿真验证

基于FPGA的 DDS连续FFT 仿真验证 1 摘要 本文聚焦 AMD LogiCORE IP Fast Fourier Transform (FFT) 核心,深入剖析其在 FPGA 设计中的应用。该 FFT 核心基于 Cooley - Tukey 算法,具备丰富特性,如支持多种数据精度、算术类型及灵活的运行时配置。文中详细介绍了其架构选项、…

美团Leaf分布式ID生成器使用教程:号段模式与Snowflake模式详解

引言 在分布式系统中&#xff0c;生成全局唯一ID是核心需求之一。美团开源的Leaf提供了两种分布式ID生成方案&#xff1a;号段模式&#xff08;高可用、依赖数据库&#xff09;和Snowflake模式&#xff08;高性能、去中心化&#xff09;。本文将手把手教你如何配置和使用这两种…

Swift 并发任务的协作式取消

在 Swift 并发&#xff08;Swift Concurrency&#xff09;中&#xff0c;任务&#xff08;Task&#xff09;不会被强行终止&#xff0c;而是采用**协作式取消&#xff08;cooperative cancellation&#xff09;**机制。这意味着任务会被标记为“已取消”&#xff0c;但是否真正…