如何使用 NavigationStack 和 SwiftUI 发送额外数据?

2024-05-03

我有三个viewsA、B 和 C。用户可以从 A 导航到 B,也可以从 A 导航到 C。用户可以从 B 导航到 C。现在我想区分用户是从 A 到 C 还是从 B 到 C,所以我在寻找如何在 NavigationStack 中传递额外的数据,这可以帮助我区分

下面是我的代码

import SwiftUI

@main
struct SampleApp: App {
    
    @State private var path: NavigationPath = .init()
    
    var body: some Scene {
        WindowGroup {
            NavigationStack(path: $path){
                A(path: $path)
                    .navigationDestination(for: ViewOptions.self) { option in
                        option.view($path)
                    }
            }
        }
    }
    
    enum ViewOptions {
        case caseB
        case caseC
        @ViewBuilder func view(_ path: Binding<NavigationPath>) -> some View{
            switch self{
            case .caseB:
                B(path: path)
            case .caseC:
                C(path: path)
            }
        }
    }
}

struct A: View {
    @Binding var path: NavigationPath
    var body: some View {
        VStack {
            Text("A")
            Button {
                path.append(SampleApp.ViewOptions.caseB)
            } label: {
                Text("Go to B")
            }
            Button {
                path.append(SampleApp.ViewOptions.caseC)
            } label: {
                Text("Go to C")
            }
        }
    }
}

struct B: View {
    @Binding var path: NavigationPath
    var body: some View {
        VStack {
            Text("B")
            Button {
                path.append(SampleApp.ViewOptions.caseC)
            } label: {
                Text("Go to C")
            }
        }
    }
}


struct C: View {
    @Binding var path: NavigationPath
    var body: some View {
        VStack {
            Text("C")
            
        }
    }
}

而不是“传递额外的数据NavigationStack“你可以在a中传递数据NavigationRouter。它给你更多的控制权

@available(iOS 16.0, *)
//Simplify the repetitive code
typealias NavSource = SampleApp.ViewOptions
@available(iOS 16.0, *)
struct NavigationRouter{
    var path: [NavSource] = .init()
    ///Adds the provided View to the stack
    mutating func goTo(view: NavSource){
        path.append(view)
    }
    ///Searches the stack for the `View`, if the view is `nil`, the stack returns to root, if the `View` is not found the `View` is presented from the root
    mutating func bactrack(view: NavSource?){
        guard let view = view else{
            path.removeAll()
            return
        }
        //Look for the desired view
        while !path.isEmpty && path.last != view{
            path.removeLast()
        }
        //If the view wasn't found  add it to the stack
        if path.isEmpty{
            goTo(view: view)
        }
    }
    ///Identifies the previous view in the stack, returns nil if the previous view is the root
    func identifyPreviousView() -> NavSource?{
        //1 == current view, 2 == previous view
        let idx = path.count - 2
        //Make sure idx is valid index
        guard idx >= 0 else{
            return nil
        }
        //return the view
        return path[idx]
    }
}

一旦您可以访问路由器View您可以进行相应调整。

@available(iOS 16.0, *)
struct SampleApp: View {
    @State private var router: NavigationRouter = .init()
    var body: some View {
        NavigationStack(path: $router.path){
            A(router: $router)
            //Have the root handle the type
            .navigationDestination(for: NavSource.self) { option in
                option.view($router)
            }
        }
    }
    //Create an `enum` so you can define your options
    //Conform to all the required protocols
    enum ViewOptions: Codable, Equatable, Hashable{
        case caseB
        case caseC
        //If you need other arguments add like this
        case unknown(String)
        //Assign each case with a `View`
        @ViewBuilder func view(_ path: Binding<NavigationRouter>) -> some View{
            switch self{
            case .caseB:
                B(router: path)
            case .caseC:
                C(router: path)
            case .unknown(let string):
                Text("View for \(string.description) has not been defined")
            }
        }
    }
}
@available(iOS 16.0, *)
struct A: View {
    @Binding var router: NavigationRouter
    var body: some View {
        VStack{
            Button {
                router.goTo(view: .caseB)
            } label: {
                Text("To B")
            }
            Button {
                router.goTo(view: .caseC)
            } label: {
                Text("To C")
            }
        }.navigationTitle("A")
    }
}
@available(iOS 16.0, *)
struct B: View {
    @Binding var router: NavigationRouter
    var body: some View {
        VStack{
            Button {
                router.goTo(view: .caseC)
            } label: {
                Text("Hello")
            }
            
        }.navigationTitle("B")
    }
}
@available(iOS 16.0, *)
struct C: View {
    @Binding var router: NavigationRouter
    //Identify changes based on previous View
    var fromA: Bool{
        //nil is the root
        router.identifyPreviousView() == nil
    }
    var body: some View {
        VStack{
            Text("Welcome\(fromA ? " Back" : "" )")

            Button {
                //Append to the path the enum value
                router.bactrack(view: router.identifyPreviousView())
            } label: {
                Text("Back")
            }
            Button {
                //Append to the path the enum value
                router.goTo(view: .unknown("\"some other place\""))
            } label: {
                Text("Next")
            }
            
        }.navigationTitle("C")
            .navigationBarBackButtonHidden(true)
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 NavigationStack 和 SwiftUI 发送额外数据? 的相关文章

随机推荐

  • 删除最低位

    给定一个二进制数 删除最低位的最快方法是什么 01001001010 gt 01001001000 它将在代码中用于迭代变量的位 伪代码如下 while bits 0 index getIndexOfLowestOrderBit bits
  • Ember 模型中的自定义请求 url

    我正在尝试将 Ember 数据与已构建的 REST api 一起使用 它适用于顶级路由 例如我在 api 端有课程路由 如下所示 app get courses app controllers courses findAll app get
  • 如何在android中的网格视图中进行分页? [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 如何在 android 中对 gri
  • 如何在代码中停止 autopep8 未安装消息

    我是一名新的 Python 程序员 使用 Mac 版本的 VS Code 1 45 1 创建 Django 项目 我安装了 Python 和 Django 扩展 每次我保存 Django 文件时 代码都会弹出此窗口 Formatter au
  • $rootScope.currentUser 刷新时为空

    我能够让 firebaseSimpleLogin 正常工作并将当前用户存储在 rootScope 中 当我转到另一个页面并返回提要页面时 所有内容都会加载 但是当我刷新时 rootScope currentUser 为空 其他人遇到过这个问
  • 查找-exec选项

    比如说 我想找到一些文件并执行 chmod 并使用另一个命令对其执行某些操作 例如 find name txt exec chmod 666 cp dst it says find missing argument to exec 我该如何
  • Django/gevent socket.IO 与 redis pubsub。我把东西放在哪里?

    我有一个独立的 python 脚本 它只是从 Twitter 的流 API 捕获数据 然后在收到每条消息时 使用 redis pubsub 将其发布到频道 tweets 这是该脚本 def main username username pa
  • 可视化时间序列时标记特定日期

    我有一个包含几年数据的时间序列 例如 ts pd Series np random randn 1000 index pd date range 1 1 2000 periods 1000 ts ts cumsum ts plot 我还有两
  • 基于鼠标位置的平滑滚动(Jquery)

    HI 我想创建一个基于鼠标位置的平滑滚动条 这个想法是创建一个具有固定宽度的外部 div 内容非常宽 必须根据鼠标位置向左或向右滚动 如果内容是 无限 或 无尽 的 那就太好了 内容是一个非常宽的图像 无缝 地重复 有人可以帮我用 jQue
  • Python:如何删除圆括号内的文本?

    我试过了 但没用 return re sub myResultStats text 建议 thanks 尝试这个 return re sub myResultStats text 括号表示捕获组 因此您必须转义它们
  • 将字符缓冲区从 .NET 传递到 COM 并获取更新

    我有从 C 调用以下 COM 方法 该方法在提供的缓冲区中返回一个字符串pchText 这是not必须以零结尾 和复制的字符数pcch HRESULT Next in out long pcch out size is pcch OLECH
  • 使用 cURL 设计身份验证

    如何使用 Devise 从终端使用 cURL 验证我的 Ruby on Rails 应用程序 我想 curl user email password http domain bla api auth sign in 并正在回应 您要查找的页
  • 作为属性的类引用

    谷歌对于这类搜索毫无用处 因为你会得到数亿个结果 其中没有一个与特定问题相关 问题很简单 Delphi 中是否可以有类引用属性 如果是这样 怎么办 这是我尝试过的 type TMyObject class end TMyObjectClas
  • 标准在哪里谈论别名?

    C 标准中哪里谈到了别名 我查看了目录 没有看到 别名 这个词 我试图查看一个定义规则 3 2 但搜索 别名 没有结果 我不知道它可能在哪里 我正在寻找内存别名 别名主要在 3 10 basic lval 10中讨论 If a progra
  • 无法从 WebDriver 获取正确的控制台日志(Chrome、C#)

    我在 Selenium WebDriver C Chrome 浏览器中编写了以下微测试 它没有用 但这里不是这种情况 Test public void T2 API 001 PrintingAlerts pgactions OpenData
  • 为 Rails 3 应用程序制作自定义插件/gem/引擎

    我正在遵循指南http edgeguides rubyonrails org plugins html http edgeguides rubyonrails org plugins html而且它似乎有点过时了 您能看一下并告诉我哪些部分
  • 比较 .NET 中的两个字节数组

    我怎样才能快速做到这一点 当然我可以这样做 static bool ByteArrayCompare byte a1 byte a2 if a1 Length a2 Length return false for int i 0 i
  • 识别 Windows 版本

    我正在编写一个打印出详细 Windows 版本信息的函数 输出可能是这样的元组 32bit XP Professional SP3 English 它将支持 Windows XP 及更高版本 我一直坚持获取 Windows 版本 例如 专业
  • 使用 Flask 时在 Python 中实现持久数据库连接的最佳实践

    我的问题是关于在生产环境或其他关注性能的环境中使用 Flask 时处理数据库连接的推荐方法 在 Flask 中 g 对象可用于存储内容 并且可以将打开的数据库连接放置在那里 以允许应用程序在同一请求期间的后续数据库查询中重用它们 但是 g
  • 如何使用 NavigationStack 和 SwiftUI 发送额外数据?

    我有三个viewsA B 和 C 用户可以从 A 导航到 B 也可以从 A 导航到 C 用户可以从 B 导航到 C 现在我想区分用户是从 A 到 C 还是从 B 到 C 所以我在寻找如何在 NavigationStack 中传递额外的数据