SwiftUI Navigation Stack — 如何进行深度链接以及新增功能

SwiftUI Navigation Stack — 如何进行深度链接以及新增功能

iOS Developers when seeing the new Navigation Stack on WWDC2022

你好呀!这正是我在今年 WWDC 上宣布新的 Navigation Stack 时所说的,我对此非常高兴。我快乐的基础是我确切地知道我将用它做什么!

就在我的脑海里,我有一个想法:Deeplinks 导航终于!从那天起,因为我没有时间做,但时间到了,这将是我关于 Medium 的第一篇文章,并开始介绍 iOS16 中所有新的 SwiftUI 功能的系列文章。所以让我们开始派对吧!

好的,但发生了什么变化? 对于不熟悉该主题的人,我将快速浏览一下以前版本的 SwiftUI 中导航和深度链接的外观。因此,在我们作为开发人员使用 NavigationView 和 NavigationLink 之前,这将使我们能够在应用程序中导航用户,它看起来像这样:

 结构特征:可识别、可散列、可解码{  
 var id: String = UUID().uuidString  
 让标题:字符串  
 让描述:字符串  
 让类型:FeatureType  
 } 枚举 FeatureType:字符串,可解码 {  
 案例图表  
 箱规  
 } 最终类 ContentViewModel: ObservableObject {  
  
 @Published var selectedFeature:功能?  
 @Published var showFeatureScreen: Bool = false  
      
 @ViewBuilder func showFeature() -> 一些视图 {  
 如果让特征 = selectedFeature {  
 开关功能。类型{  
 案例.charts:  
 ChartsScreen(功能:功能)  
 案例.gauge:  
 GaugeScreen(特征:特征)  
 }  
 }  
 }  
 } 结构内容视图:查看{  
 @StateObject var viewModel = ContentViewModel()  
  
 var body: 一些视图 {  
 导航视图 {  
 ZStack {  
 NavigationLink(isActive: $viewModel.showFeatureScreen) {  
 viewModel.showFeature()  
 } 标签: {}  
                  
 滚动视图 {  
 LazyVStack(间距:8){  
 ForEach(viewModel.features) { 特征  
 FeatureCell(特征:特征){  
 viewModel.selectedFeature = 特征  
 viewModel.showFeatureScreen = true  
 }  
 }  
 }  
 }  
 .navigationTitle("iOS16 功能")  
 .onOpenURL { 网址在  
 print(" \(url)")  
                      
 守卫让组件= URLComponents(url:url,resolvingAgainstBaseURL:true)else { return }  
 让查询 = components.queryItems ?? []  
 让主机 = components.host  
 让方案 = components.scheme  
                      
 如果方案==“showdownRouting”&&主机==“功能”{  
 var jsonQuery = query.map { "\"\($0.name)\":\"\($0.value ?? "")\"" }.joined(分隔符: ",")  
 jsonQuery = "{\(jsonQuery)}"  
                          
 守卫让 jsonData = jsonQuery.data(使用: .utf8) else {  
 返回  
 }  
                          
 做 {  
 让特征 = 尝试 JSONDecoder.shared.decode(Feature.self, from: jsonData)  
 viewModel.selectedFeature = 特征  
 viewModel.showFeatureScreen = true  
 } 抓住 {  
 打印(错误)  
 }  
 }  
 }  
 }  
 }  
 }  
 }

Old NavigatonView and NavigationLink Deeplink

这是您以旧方式处理简单深层链接的方式,正如您所看到的,这种方法的问题是一次只能打开一个屏幕,从长远来看这很麻烦。然后,当您在树中打开一些导航时,您将面临缺少 pop-to-root 方法的问题。并且您需要使与导航树相关的所有绑定无效。

好吧,这个有问题 但是我们能用它做什么呢?导航栈!

新的 导航栈导航路径 UIKit 开发人员会非常熟悉,他们会喜欢这样:

 枚举 FeatureType:字符串,可解码 {  
 案例图表  
 箱规  
 }  
  
 结构特征:可识别、可散列、可解码{  
 var id: String = UUID().uuidString  
 让标题:字符串  
 让描述:字符串  
 让类型:FeatureType  
 }  
  
 最终类 ContentViewModel: ObservableObject {  
 @Published var navigationPath = NavigationPath()  
  
 var 特征:[特征] = [  
 Feature(title: "图表",  
 description: "使用图表在 SwiftUI 视图中构建富有表现力和动态的数据可视化。",  
 类型:.charts),  
 特征(标题:“仪表”,  
 description: "SwiftUI 引入了一个名为 Gauge 的新视图来显示进度。在最基本的形式中,仪表的默认范围是 0 到 1。",  
 类型:.gauge)  
 ]  
  
   **func showFeature(_ feature: Feature) {  
 navigationPath.append(功能)  
 }**  
 }  
  
 结构内容视图:查看{  
 @StateObject var viewModel = ContentViewModel()  
  
 var body: 一些视图 {  
 NavigationStack(路径:$viewModel.navigationPath){  
 滚动视图 {  
 LazyVStack(间距:8){  
 ForEach(viewModel.features) { 特征  
 FeatureCell(特征:特征){  
 viewModel.showFeature(特征)  
 }  
 }  
                    **.navigationDestination(for: Feature.self) { 特征在  
 开关功能。类型{  
 案例.charts:  
 ChartsScreen(功能:功能)  
 案例.gauge:  
 GaugeScreen(特征:特征)  
 }  
 }**  
 .navigationTitle("iOS16 功能")  
 }  
 .onOpenURL { 网址在  
 print(" \(url)")  
                      
 守卫让组件= URLComponents(url:url,resolvingAgainstBaseURL:true)else { return }  
 让查询 = components.queryItems ?? []  
 让主机 = components.host  
 让方案 = components.scheme  
                      
 如果方案==“showdownRouting”&&主机==“功能”{  
 var jsonQuery = query.map { "\"\($0.name)\":\"\($0.value ?? "")\"" }.joined(分隔符: ",")  
 jsonQuery = "{\(jsonQuery)}"  
                          
 守卫让 jsonData = jsonQuery.data(使用: .utf8) else {  
 返回  
 }  
                          
 做 {  
 让特征 = 尝试 JSONDecoder.shared.decode(Feature.self, from: jsonData)  
 viewModel.showFeature(特征)  
 } 抓住 {  
 打印(错误)  
 }  
 }  
 }  
 }  
 }  
 }  
 }

如您所见,我们将 NavigatonPath 对象保留在 ViewModel 中,我们可以向其推送各种数据,例如 Feature,然后对其做出反应,在这种情况下,为了简单起见,我只检查它是什么类型。这种方法非常适合 SwiftUI,同时专注于建模数据和状态。

这使我们能够向堆栈添加更多内容,并通过将 navigationPath 向下传递到我们在 NavigationPath 上推送的视图来轻松弹出堆栈的根:

 .navigationDestination(for: Feature.self) { 特征在  
 开关功能。类型{  
 案例.charts:  
                           **ChartsScreen(功能:功能,导航路径:$viewModel.navigationPath)**  
 案例.gauge:  
 GaugeScreen(特征:特征)  
 }  
 } // 图表屏幕实现:  
 结构图表屏幕:查看{  
 var 特征:特征  
 @Binding var navigationPath: NavigationPath  
 @StateObject var viewModel = ChartsViewModel()  
  
 var body: 一些视图 {  
 堆栈{  
 文本(特征.描述)  
 .font(.footnote)  
 。填充()  
 .multilineTextAlignment(.center)  
 .onTapGesture {  
                 **navigationPath.removeLast(navigationPath.count)**  
 }  
              
 间隔()  
  
 堆栈{  
 按钮 {  
 带动画{  
 viewModel.team = viewModel.team.sorted { $0.seniority < $1.seniority }  
 }  
 } 标签: {  
 文本(“排序”)  
 .foregroundColor(.white)  
 。填充()  
 .background(.green)  
 .cornerRadius(10)  
 }  
  
 按钮 {  
 带动画{  
 viewModel.team = viewModel.team.shuffled()  
 }  
 } 标签: {  
 文本(“随机播放”)  
 .foregroundColor(.white)  
 。填充()  
 .background(.red)  
 .cornerRadius(10)  
 }  
 }  
  
 滚动视图 {  
 条形图  
 折线图  
 面积图  
 }  
 }  
 .navigationTitle(功能。标题)  
 .navigationBarTitleDisplayMode(.inline)  
 }

这是效果:

正如你所看到的,实现非常简单,我很高兴我们将能够在不久的将来使用它,而新 iPhone 即将问世!

所有源代码都是公开的,并将在该系列的下一集中更新有关新功能的内容。

[

iOS-16-MacOS-13-SwiftUI-Showdown 下载iOS-16-MacOS-13-SwiftUI-Showdown的源码_GitHub_帮酷

新的 SwiftUI 4 具有适用于 iOS16+ 的示例应用程序。为 LSWarss/iOS-16-macOS-13-SwiftUI-Showdown 的开发做出贡献...

github.com

](https://github.com/LSWarss/iOS-16-MacOS-13-SwiftUI-Showdown)

如果您对接下来会发生什么等感到好奇,请在 GitHub 上关注它。感谢您的阅读,我很好奇您是否喜欢这种形式的文章。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明

本文链接:https://www.qanswer.top/3024/08213109

posted @ 2022-08-31 09:08  哈哈哈来了啊啊啊  阅读(719)  评论(0编辑  收藏  举报