Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >SwiftUI中navigationDestination用法

SwiftUI中navigationDestination用法

作者头像
莫空9081
发布于 2024-11-20 06:01:57
发布于 2024-11-20 06:01:57
20700
代码可运行
举报
文章被收录于专栏:iOS 备忘录iOS 备忘录
运行总次数:0
代码可运行

背景

最近做 SwiftUI 项目,之前对于 navigationDestination 的用法理解不太深刻,觉得很是难用,最近发现了正确的使用方式,这里记录一下。

场景

假设有一个 TabView 类为 A,A 有 B、C 两个Tab,C 的 Tab 下子界面有 D,D 的子界面有 E。

即有 A -> B 和 A -> C -> D -> E 两条链路。

之前的用法是:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

struct A: View {
    var body: some View {
        NavigationStack {
            TabView(selection: $selectedTab) {
                B()
                C()
            }
        }
    }
}

struct B: View {

}

struct C: View {
    @State private var navigateToD: Bool = false

    var body: some View {
        VStack {
            xxx
            Button {
                navigateToD.toggle()
            } label: {
                Text("NavigateToD")
            }
        }
        .navigationDestination(isPresented: $navigateToD) {
            D()
        }
    }
}

struct D: View {
    @State private var navigateToE: Bool = false

    var body: some View {
        VStack {
            xxx
            Button {
                navigateToE.toggle()
            } label: {
                Text("NavigateToD")
            }
        }
        .navigationDestination(isPresented: $navigateToE) {
            E()
        }
    }
}

struct E: View {
    xxx
}

这里面简单的使用确实没问题,每个界面的返回可以通过 Environment 的dismiss 来实现。但是如果想要实现从 E 返回到 C 就非常麻烦了。而且,这里每一步的跳转都散落在各个类里,没有统一的地方管理,后续维护也不易。

所以针对上面存在的问题,对使用进行了优化,

针对TabView 的两个子视图,B 和 C,分别用NavigationStack包装。不要把NavigationStack放在TabView的外层,因为遇到了放在这里,针对navigationDestination做跳转的时候,遇到了跳转多次的问题。

声明一个BNavCoordinatorCNavCoordinator,分别用于管理BC的跳转。在具体的NavCoordinator中,声明一个枚举管理这个页面下的所有子界面。然后创建NavCoordinator,实现pushpoppopToRootnavigator方法。 示例代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
enum CNavScreens: Hashable {
    case d(param1: Int, param2: String)
    case e
}

struct CNavCoordinator: ObservableObject {
    @Published var paths = NavigationPath()

    @ViewBuilder
    func navigate(to screen: CNavScreens) -> some View {
        switch screen {
            case .d(let param1, let param2):
                D(param1: param1, param2: param2)
            case  .e:
                E()
        }
    }


   // add screen
   func push(_ screen: TGICustomerScreens) {
       paths.append(screen)
   }
   
   // remove last screen
   func pop() {
       paths.removeLast()
   }
   
   // popToRoot
   func popToRoot() {
       paths.removeLast(paths.count)
   }
}

然后在具体页面中使用,示例如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

struct A: View {
    var body: some View {
         TabView(selection: $selectedTab) {
             B()
             C()
         }
    }
}

struct B: View {

}

struct C: View {
    @StateObject var cNavCoordinator = CNavCoordinator()

    var body: some View {
        NavigationStack {
          VStack {
              xxx
              Button {
                let screen = CNavScreens.d(param1: param1, param2: param2)
                cNavCoordinator.push(screen)
              } label: {
                  Text("NavigateToD")
              }
          }
          .environmentObject(navCoordinator)
          .navigationDestination(for: CustomScreens.self) { path in
              navCoordinator.navigate(to: path)
                  .environmentObject(navCoordinator)
                  .environmentObject(xxx)
                  .environmentObject(yyy)
          }
        }
    }
}

struct D: View {
    @EnvironmentObject var cNavCoordinator: CNavCoordinator

    var body: some View {
        VStack {
            xxx
            Button {
                let screen = CNavScreens.e
                cNavCoordinator.push(screen)
            } label: {
                Text("NavigateToD")
            }
        }
    }
}

struct E: View {
     @EnvironmentObject var cNavCoordinator: CNavCoordinator

    var body: some View {
        VStack {
            xxx
            Button {
                // cNavCoordinator.pop()
                cNavCoordinator.popToRoot()
            } label: {
                Text("BackToC")
            }
        }
    }
}

这样所有的跳转其实都是在根类 B 和 C 中管理,避免了分散到每个页面的逻辑。同时可以方便返回到根视图。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-08-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
解析 SwiftUI 中两处由状态更新滞后引发的严重 Bug
众所周知,SwiftUI 是一个响应式框架,这意味着,当数据源发生变化时,框架会自动更新视图。同样,当我们想调整视图显示时,应直接对状态进行修改。但是,SwiftUI 中的一些系统控件并没有完全遵循响应式的设计原则,由此在某些情况下会出现严重的错误,影响用户体验,并使开发者无所适从。
东坡肘子
2023/09/01
1.1K0
解析 SwiftUI 中两处由状态更新滞后引发的严重 Bug
SwiftUI 4.0 的全新导航系统
长久以来,开发者对 SwiftUI 的导航系统颇有微词。受 NavigationView 的能力限制,开发者需要动用各种技巧乃至黑科技才能实现一些本应具备基本功能(例如:返回根视图、向堆栈添加任意视图、返回任意层级视图 、Deep Link 跳转等 )。SwiftUI 4.0( iOS 16+ 、macOS 13+ )对导航系统作出了重大改变,提供了以视图堆栈为管理对象的新 API ,让开发者可以轻松实现编程式导航。本文将对新的导航系统作以介绍。
东坡肘子
2022/07/28
10.7K0
SwiftUI 4.0 的全新导航系统
在 SwiftUI 中创建自适应的程序化导航方案
随着苹果对 iPadOS 的不断投入,越来越多的开发者都希望自己的应用能够在 iPad 中有更好的表现。尤其当用户开启了台前调度( Stage Manager )功能后,应用对不同视觉大小模式的兼容能力就越发显得重要。本文将就如何创建可自适应不同尺寸模式的程序化导航方案这一内容进行探讨。
东坡肘子
2022/12/16
4.5K0
在 SwiftUI 中创建自适应的程序化导航方案
从用SwiftUI搭建项目说起
后续这个SwiftUI分类的文章全部都是针对SwiftUI的日常学习和理解写的,自己利用Swift写的第二个项目也顺利上线后续的需求也不是特着急,最近正好有空就利用这段时间补一下自己对SwiftUI的理解,这个过程当中正好把整个学习过程记录下来,方便自己查阅,也希望能给需要的同学一点点的帮助。由于自己还欠着RxSwift的帐,这次也是想着先放弃别的账务(欠的的确挺多的)先全心全意的把这两块的帐给补补,希望补上这笔账之后自己对Swift的理解也能上一个台阶,对Siwft的理解自认为还是感觉欠缺的,不算是真的深入的掌握,我对SwiftUI也是在学习当中,现在能查阅的关于SwiftUI的资料很多是需要收费的,遇到问题只能想办法努力解决,有写的不钟意的地方,希望多加指正!
Mr.RisingSun
2020/12/16
4.7K0
从用SwiftUI搭建项目说起
SwiftUI 在 WWDC 24 之后的新变化
WWDC 24 已经到来,我们有很多内容要讨论。每年,SwiftUI 都会通过引入更多功能来赶上 UIKit。今年也不例外。让我们深入了解 SwiftUI 框架引入的新功能。
Swift社区
2024/09/16
3850
SwiftUI 在 WWDC 24 之后的新变化
解析SwiftUI布局细节(二)循环轮播+复杂布局
上一篇我们总结的主要是VStack里面的东西,由他延伸到 @ViewBuilder, 接着我们上一篇总结的我们这篇内容主要说的是下面的几点,在这些东西说完后我准备解析一下苹果在SiwftUI文档中说道的比较好玩的一个东西,具体的我们后面在看。这篇我们还是说我们关于SwiftUI的东西,再提一下Demo代码我已经提交上Git了,目前Demo进度为一级页面基本上结束,地图点击大头针的添加也刚处理完,代码有需要的小伙伴可以去Git看看,项目地址
Mr.RisingSun
2021/01/06
12.5K1
解析SwiftUI布局细节(二)循环轮播+复杂布局
SwiftUI 状态管理系统指南
SwiftUI与苹果之前的UI框架的区别不仅仅在于如何定义视图和其他UI组件,还在于如何在整个使用它的应用程序中管理视图层级的状态。
Swift社区
2022/07/05
5.3K0
掌握 Transaction,实现 SwiftUI 动画的精准控制
SwiftUI 因其简便的动画 API 与极低的动画设计门槛而广受欢迎。但是,随着应用程序复杂性的增加,开发者逐渐发现,尽管动画设计十分简单,但要实现精确细致的动画控制并非易事。同时,在 SwiftUI 的动画系统中,有关 Transaction 的解释很少,无论是官方资料还是第三方文章,都没有对其运作机制进行系统的阐述。
东坡肘子
2023/07/08
6470
掌握 Transaction,实现 SwiftUI 动画的精准控制
如何在 SwiftUI 中创建悬浮操作按钮
悬浮操作按钮(Floating Action Button, FAB)是一种在 Android 和 Material Design 中使用的 UI 元素。它用于触发特定屏幕的主要操作。
Swift社区
2024/06/14
8180
如何在 SwiftUI 中创建悬浮操作按钮
探讨 SwiftUI 中的几个关键属性包装器
在这篇文章中,我们将探讨几个在 SwiftUI 开发中经常使用且至关重要的属性包装器。本文旨在提供对这些属性包装器的主要功能和使用注意事项的概述,而非详尽的使用指南。
东坡肘子
2023/12/21
6870
探讨 SwiftUI 中的几个关键属性包装器
React Native导航器之react-navigation使用
在上一节Navigation组件,我们使用系统提供的导航组件做了一个跳转的例子,不过其实战能力不强,这里推荐一个超牛逼的第三方库:react-navigation。在讲react-navigation之前,我们先看一下常用的导航组件。 导航控件 常见的导航主要分为三种: 1.StackNavigator :类似于普通的Navigator,屏幕上方导航栏 2.TabNavigator:obviously, 相当于iOS里面的TabBarController,屏幕下方标签栏 3.DrawerNavi
xiangzhihong
2018/02/06
13K0
React Native导航器之react-navigation使用
@StateObject 研究
在我之前的文章@State研究中我们探讨过@State,通过它,我们可以方便的将值类型数据作为View的Source of truth。在SwiftUI 1.0时代,如果想将引用类型作为source of truth,通常的方法是使用@EnvironmentObject或者 @ObservedObject。
东坡肘子
2022/07/28
1.2K0
如何在SwiftUI中实现interactiveDismissDisabled
由于健康笔记[2]中数据录入都是在Sheet中进行的,为了防止用户在录入过程中由于误操作(使用手势取消Sheet)丢失数据,因此,从最初的版本开始,我就一直使用各种手段加强对Sheet的控制。
东坡肘子
2022/07/28
4.3K0
如何在SwiftUI中实现interactiveDismissDisabled
SwiftUI-数据流
SwiftUI中的界面是严格数据驱动的:运行时界面的修改,只能通过修改数据来间接完成,而不是直接对界面进行修改操作。
YungFan
2020/02/18
10.3K1
SwiftUI-数据流
Ask Apple 2022 与 SwiftUI 有关的问答(下)
Ask Apple 为开发者与苹果工程师创造了在 WWDC 之外进行直接交流的机会。本文对本次活动中与 SwiftUI 有关的一些问答进行了整理,并添加了一点个人见解。本文为下篇。
东坡肘子
2022/12/16
15.5K0
Ask Apple 2022 与 SwiftUI 有关的问答(下)
WWDC 23 之后的 SwiftUI 有哪些新功能
WWDC 23 已经到来,SwiftUI 框架中有很多改变和新增的功能。在本文中将主要介绍 SwiftUI 中数据流、动画、ScrollView、搜索、新手势等功能的新变化。
Swift社区
2023/09/06
6460
WWDC 23 之后的 SwiftUI 有哪些新功能
从零开始的 Swift UI (二)
在上一篇文章中,我们完成了 HomeView 的基本布局。接下来我们来编写一下数据层(Model ViewModel)。
Innei
2021/12/28
1.5K0
一段因 @State 注入机制所产生的“灵异代码”
本文将通过一段可复现的“灵异代码”,对 State 注入优化机制、模态视图( Sheet、FullScreenCover )内容的生成时机以及不同上下文( 相互独立的视图树 )之间的数据协调等问题进行探讨。
东坡肘子
2023/03/02
2K0
一段因 @State 注入机制所产生的“灵异代码”
打造可适配多平台的 SwiftUI 应用
本文是笔者参加 2023 年 4 月 20 日 “SwiftUI 技术沙龙( 北京站 )” 活动的分享内容。基于记忆整理而成。有关本次活动的情况,可以参阅 我在北京参加 SwiftUI 技术沙龙[1] 一文。
东坡肘子
2023/05/18
2.3K0
打造可适配多平台的 SwiftUI 应用
SwiftUI 与前端框架(如 React)中的状态管理对比
在构建现代应用时,状态管理是决定应用复杂性和可维护性的关键。SwiftUI 和 React 都采用声明式 UI 模型,但它们的状态管理方式不同。本文将对比 SwiftUI 的 @State、@Binding、@EnvironmentObject 等状态管理工具与 React 的 useState、useContext,分析各自的设计理念、优缺点及最佳实践。
Swift社区
2024/09/26
8720
SwiftUI 与前端框架(如 React)中的状态管理对比
相关推荐
解析 SwiftUI 中两处由状态更新滞后引发的严重 Bug
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档