如何在 SwiftUI 中随时从子视图作为父视图访问数据?

2023-11-23

我是 SwiftUI 的新手,并且了解我可能需要以某种方式实现 EnvironmentObject,但我不确定在这种情况下如何实现。

这是Trade class

class Trade {
    var teamsSelected: [Team]

    init(teamsSelected: [Team]) {
        self.teamsSelected = teamsSelected
    }
}

这是子视图。它有一个实例trade来自Trade班级。有一个按钮可以将 1 添加到数组中teamsSelected.

struct TeamRow: View {
    var trade: Trade

    var body: some View {
        Button(action: {
            self.trade.teamsSelected.append(1)
        }) {
            Text("Button")
        }
    }
}

这是父视图。正如你所看到的,我通过了trade进入子视图TeamRow。我想trade与 同步trade in TeamRow这样我就可以通过trade.teamsSelected to TradeView.

struct TeamSelectView: View {
    var trade = Trade(teamsSelected: [])

    var body: some View {
        NavigationView{
            VStack{
                NavigationLink(destination: TradeView(teamsSelected: trade.teamsSelected)) {
                   Text("Trade")
                }

                List {
                    ForEach(teams) { team in
                        TeamRow(trade: self.trade)
                    }
                }
            }
        }
    }
}

我已经获取了您的代码并更改了一些内容来说明 SwiftUI 的工作原理,以便让您更好地了解如何使用ObservableObject, @ObservedObject, @State, and @Binding.

前面要提一件事——@ObservedObject目前,尝试在运行 iOS 13 Beta 6、7 或 8 的物理设备上运行 SwiftUI 代码时出现问题。我回答了一个问题here更详细地介绍了这一点并解释了如何使用@EnvironmentObject作为解决方法。


我们先来看看Trade。既然你想通过Trade视图之间的对象,更改该对象的属性Trade对象,然后将这些更改反映在使用该对象的每个视图中Trade对象,你会想要制作Trade an ObservableObject。我已经为你添加了一个额外的属性Trade类纯粹是为了说明目的,我稍后会解释。我将向您展示两种编写方法ObservableObject- 首先以详细的方式了解它是如何工作的,然后是简洁的方式。

import SwiftUI
import Combine

class Trade: ObservableObject {
    let objectWillChange = PassthroughSubject<Void, Never>()

    var name: String {
        willSet {
            self.objectWillChange.send()
        }
    }

    var teamsSelected: [Int] {
        willSet {
            self.objectWillChange.send()
        }
    }

    init(name: String, teamsSelected: [Int]) {
        self.name = name
        self.teamsSelected = teamsSelected
    }
}

当我们符合ObservableObject,我们可以选择编写自己的ObservableObjectPublisher,我是通过导入完成的Combine并创建一个PassthroughSubject。然后,当我想发布我的对象即将更改时,我可以调用self.objectWillChange.send()正如我所经历的willSet for name and teamsSelected.

不过,这段代码可以大大缩短。ObservableObject自动合成一个对象发布者,因此我们实际上不必自己声明它。我们还可以使用@Published声明我们的属性应该发送发布者事件而不是使用self.objectWillChange.send() in willSet.

import SwiftUI

class Trade: ObservableObject {
    @Published var name: String
    @Published var teamsSelected: [Int]

    init(name: String, teamsSelected: [Int]) {
        self.name = name
        self.teamsSelected = teamsSelected
    }
}

现在让我们看看您的TeamSelectView, TeamRow, and TradeView。再次记住我已经做了一些更改(并添加了一个示例TradeView)只是为了说明一些事情。

struct TeamSelectView: View {
    @ObservedObject var trade = Trade(name: "Name", teamsSelected: [])
    @State var teams = [1, 1, 1, 1, 1]

    var body: some View {
        NavigationView{
            VStack{
                NavigationLink(destination: TradeView(trade: self.trade)) {
                    Text(self.trade.name)
                }

                List {
                    ForEach(self.teams, id: \.self) { team in
                        TeamRow(trade: self.trade)
                    }
                }
                Text("\(self.trade.teamsSelected.count)")
            }
            .navigationBarItems(trailing: Button("+", action: {
                self.teams.append(1)
            }))
        }
    }
}
struct TeamRow: View {
    @ObservedObject var trade: Trade

    var body: some View {
        Button(action: {
            self.trade.teamsSelected.append(1)
        }) {
            Text("Button")
        }
    }
}
struct TradeView: View {
    @ObservedObject var trade: Trade

    var body: some View {
        VStack {
            Text("\(self.trade.teamsSelected.count)")
            TextField("Trade Name", text: self.$trade.name)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .padding()
        }
    }
}

我们先来看看@State var teams。我们用@State对于简单值类型 -Int, String, basic structs- 或简单值类型的集合。@ObservedObject用于符合以下条件的对象ObservableObject,我们将其用于比简单的更复杂的数据结构Int or String.

你会注意到什么@State var teams是我添加了一个导航栏项目,它将向teams按下时的数组,并且因为我们List是通过迭代生成的teams数组,我们的视图重新渲染并向我们添加一个新项目List每当按下按钮时。这是一个非常基本的示例,说明了如何使用@State.

接下来,我们有我们的@ObservedObject var trade。你会注意到我并没有真正做任何与你原来不同的事情。我仍在创建我的实例Trade类并在我的视图之间传递该实例。但既然现在已经是一个ObservableObject,我们正在使用@ObservedObject,我们的视图现在都会收到发布者事件Trade对象发生变化并将自动重新渲染其视图以反映这些变化。

我想指出的最后一件事是TextField我创建于TradeView更新Trade对象的name财产。

TextField("Trade Name", text: self.$trade.name)

The $字符表示我正在将绑定传递到文本字段。这意味着任何改变TextField使name都会体现在我的Trade目的。您可以通过声明自己做同样的事情@Binding当您尝试在视图之间同步状态而不传递整个对象时,这些属性允许您在视图之间传递绑定。

当我改变你的TradeView采取@ObservedObject var trade,你可以简单地通过teamsSelected将您的贸易观点视为这样的约束力 -TradeView(teamsSelected: self.$trade.teamsSelected)- 只要你的TradeView接受绑定。配置您的TradeView要接受绑定,您所要做的就是声明您的teamsSelected财产在TradeView像这样:

@Binding var teamsSelected: [Team]

最后,如果您在使用时遇到问题@ObservedObject实体设备上可以参考我的回答here有关如何使用的说明@EnvironmentObject作为解决方法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 SwiftUI 中随时从子视图作为父视图访问数据? 的相关文章

  • 导航栏隐藏在 SwiftUI 中不起作用

    我有三观 我想隐藏第三个视图中的导航栏 即使我给 navigationBarHidden true 导航栏正在显示 我找不到我哪里做错了 我已在下面附上我的代码和生成的屏幕截图 Xcode 版本 11 1 struct ContentVie
  • 如何跟踪 SwiftUI 应用程序中的所有触摸

    我正在尝试在 SwiftUI 应用程序中实现锁屏 我需要跟踪每个事件才能重新启动锁定计时器 在 UIKit 应用程序中 我使用了这种方法 重写 UIApplication 它允许了解应用程序中的任何事件 override func send
  • SwiftUI:如何让项目的拖放重新排序起作用?

    我有以下 SwiftUI 视图 struct ContentView View State var model Model var body some View ScrollView LazyVGrid columns columns sp
  • SwiftUI 从一个列表拖动到另一个列表

    我正在尝试在列表之间拖放 我尝试过的 我找到了一个在 UIKIt 中执行此操作并使用 UIViewControllerRepresentable 的解决方案 但这不是我想要的 另一个解决方案是在列表上使用 onDrag 但这在 iPad 上
  • SwiftUI 关闭多个模态表

    我在用 sheet isPresented self showModal 在我的根视图中呈现一个模式 在模态中 我正在使用NavigationView引导用户浏览各个页面 对于用户配置文件构建器 在导航堆栈的最后一页中 我正在使用 Envi
  • 如何使用 SwiftUI 拖动工作滑块

    我想拖动一个滑块 当然也让它滑动 我可以做其中之一 但我不能两者都做 如何拖动并拥有可用的滑块 我也尝试找到一种方法来删除手势 但我找不到方法来做到这一点 还尝试了 Apple Composition SwiftUI Gestures 文档
  • 剪裁为形状的 SwiftUI 图像在上下文菜单中具有透明填充

    在我的 SwiftUI 应用程序中 我的资产目录中有一张宽高比为 1 1 的图像 在我的代码中 我有一个Image使用不同的宽高比查看 将图像裁剪为新尺寸 Image My Image resizable aspectRatio conte
  • SwiftUI NavigationView 看不到图像

    我有一个代码并制作 NavigationLink 按钮 我编写文本和图像 但我的图像看不到 请帮助我 VStack Image Coachs resizable aspectRatio contentMode fill frame widt
  • 在 SwiftUI 文档应用程序中,如何从函数内保存文档

    当前版本的 Xcode 版本 12 5 1 为 macOS 的基于文档的应用程序提供了一个模板 提供以下文档模型 struct MyDocument FileDocument var text String init text String
  • 在 iOS 上将 SwiftUI 视图转换为 PDF

    我用 SwiftUI 画了一些漂亮的图表 因为它非常简单且容易做 然后我想将整个 SwiftUI 视图导出为 PDF 以便其他人可以以良好的方式查看图表 SwiftUI 没有直接为此提供解决方案 Cheers Alex 经过一番思考 我想到
  • 在 HStack 中以正确的方式对齐两个 SwiftUI 文本视图

    我有一个包含两行的简单列表视图 每行包含两个文本视图 查看一和查看二 我想对齐每行中的最后一个标签 查看两个 以便名称标签领先对齐并保持对齐 无论字体大小如何 第一个标签 查看一个 也需要前导对齐 我尝试在第一个标签 查看一个 上设置最小框
  • SwiftUI:如何更新由一组静态数据驱动的列表并从另一组动态数据中提取一些信息?

    我什至不确定标题问题是否有意义 不管怎样 请继续阅读 编辑 交叉链接到苹果开发者论坛 https developer apple com forums thread 663208 编辑 这是源代码 http git morpheu5 net
  • 如何修复TabView中NavigationView中List下的灰色条?

    所以我遇到一个问题 在我的列表下方出现一个灰色条 当我单击一个单元格转到另一个视图时 会出现一个更大的灰色条 这是列表视图的代码 VStack NavigationView VStack List ForEach answersArray
  • 如何为PDFView设置PDFPageOverlayViewProvider?

    更新 我正在尝试设置pageOverlayViewProvider for a PDFView并且它没有按预期工作 PDFPageOverlayViewProvider方法没有被调用 PDFViewDelegate方法运行良好 struct
  • SwiftUI 表单中的动态行高

    我正在向 SwiftUI 表单添加控件以帮助用户输入数据 并限制条目 尽管 Forms 有很多值得喜欢的地方 但我发现在该容器之外运行良好的东西在容器内却会发生非常意想不到的事情 并且如何弥补这一点并不总是显而易见的 计划是将数据字段显示为
  • SwiftUI 动画滑入和滑出

    我有一个视图将显示在另一个视图上 视图动画完美地从右侧滑入 但是当我单击 关闭 按钮时 视图消失 而没有在消失之前滑回右侧的所需动画 我尝试过使用 opacity self isShowing 1 0 但随后视图淡入和淡出 我需要它滑入和滑
  • 如何在 SwiftUI 中仅使用 ForEach 而不是列表来滑动删除

    我正在 SwiftUI 中使用 ForEach 制作自定义列表 我的目标是进行滑动删除手势 而不是将 ForEach 嵌入到列表中 到目前为止 这是我的代码 import SwiftUI struct ContentView View le
  • 当我输入字符时,SwiftUI 中的 TextField 失去焦点

    当我在文本字段中输入字符时遇到问题 在练习集视图 我必须重新单击文本框才能输入另一个字符 如果我从文本字段中删除绑定 我可以流畅地输入文本 我认为这与我的演讲者班级和更新集函数重新创建一个集合实例 因为我必须替换数组中两层深处的一些值 Co
  • SwiftUI 意外地自动弹出 NavigationLink

    我有一个简单的用例 其中一个屏幕使用 NavigationLink 推送另一个屏幕 iOS 14 5 有一个奇怪的行为 即推送的屏幕在被推送后立即弹出 Code NavigationLink destination EmptyView Em
  • 在 SwiftUI 中使用可观察对象切换视图

    我正在练习尝试使用 SwiftUI 中的可观察对象切换视图 但我的代码无法正常工作 我知道我可以用 State 来做到这一点 但我想用可观察的对象来实现这一点 当我单击内容视图中的图像时 图像不会改变 有人能帮我吗 内容视图 swift i

随机推荐

  • 如何查找当前页面使用了哪些CSS文件[重复]

    这个问题在这里已经有答案了 我的页面上有很多 CSS 文件 但其中很多文件并没有被样式使用 是否可以确定哪些文件被页面使用 哪些文件不被页面使用 Use http getfirebug com 来调试页面 当查看 css 时 它将引用使用的
  • ng 服务无法在 Docker 容器中工作

    我有这个Docker Compose 配置我只需创建一个 NodeJS 容器并在其中安装 Angular CLI After a docker compose up d 我可以在容器内通过 SSH 连接docker compose run
  • 将程序拆分为 4 个线程比单个线程慢

    过去一周我一直在编写一个光线追踪器 并且已经达到了足够多线程的程度 我尝试过使用 OpenMP 来并行化它 但是使用更多线程运行它实际上比使用一个线程运行它要慢 阅读其他类似的问题 尤其是有关 OpenMP 的问题 一个建议是 gcc 可以
  • Django 服务器错误:端口已在使用中

    重新启动 Django 服务器显示以下错误 this port is already running 此问题专门出现在 Ubuntu 上 而不是其他操作系统上 如何释放端口以重新启动服务器 更简单的解决方案只需键入sudo fuser k
  • 24小时制转换为12小时制?

    您好 我正在使用 Android 应用程序 我正在尝试弄清楚如何将 24 小时时间转换为 12 小时时间 Example 24 hour format 12 18 00 to 12 hour format 12 18pm 尝试使用Simpl
  • 将列表分割成 n 个几乎相等长度的分区[重复]

    这个问题在这里已经有答案了 我正在寻找一种快速 干净 Pythonic 的方法来将列表精确地划分为 n 个几乎相等的分区 partition 1 2 3 4 5 5 gt 1 2 3 4 5 partition 1 2 3 4 5 2 gt
  • select * from table_name where 列如 ' '

    我需要查找包含 html 代码 例如 nbsp 的记录但是当我尝试运行select from table name where column like nbsp 我收到提示询问 nbsp 的值 我猜数据库认为nbsp是一个参数 我想知道是否
  • 为什么 ad hoc ipa 在一台设备上安装失败,但在另一台具有相同 iOS 版本的设备上安装成功?

    我有一位客户 其 iPad 2 iOS 5 0 能够安装临时 ipa 但他的 iPhone 也是 iOS 5 0 完全相同的版本 在尝试使用 Windows iTunes 安装时在他的设备上收到以下消息 iTunes 同步 应用程序名称 安
  • 如何从 GitHub Actions 部署 AWS Amplify 应用程序?

    我想从 GitHub Actions 控制 Amplify 部署 因为 Amplify 自动构建 不提供GitHub环境 不观察 CI 的故障并无论如何都会进行部署 或者 要求我复制 CI 设置并在 Amplify 中重新运行它 不支持运行
  • ASP.NET 解析器错误无法加载后面的代码

    嘿我收到以下错误 解析器错误 描述 解析服务此请求所需的资源时发生错误 请查看以下特定解析错误详细信息并适当修改您的源文件 解析器错误消息 无法加载类型 AddToCart 来源错误 Line 1 Line 2 Line 3
  • 自动生成Java源代码

    我正在寻找一种方法 根据类中定义的字段 在现有 Java 源代码文件中自动生成新方法的源代码 本质上 我希望执行以下步骤 读取并解析SomeClass java 遍历源代码中定义的所有字段 添加源码方法someMethod Save Som
  • 什么是“程序类型已存在”?

    当我尝试构建我的项目时 我收到此错误 程序类型已存在 android support v4 accessibilityservice AccessibilityServiceInfoCompat Message kind ERROR tex
  • 角度反应形式:动态选择下拉值不具有约束力

    我有两个数据数组 AssociatedPrincipals 以前保存的数据 和 ReferencePrincipals 在下拉控件中填充的静态数据 我正在努力从 AssociatedPrincipals 获取先前的值以在 a 中显示 选择动
  • 如何转义 RMarkdown 块?

    我正在尝试将 RMarkdown 中的代码块的语法呈现为 pdf 最终输出应该是这样的 r some code 而不仅仅是 some code 可以在 RStudio 网站上找到解决此问题的最佳选项 请参阅有关将逐字 R 块放入 rmark
  • 将“if/else”与 OnClick 结合使用

    首先 是否可以直接在带有 onclick 属性的 html 中编写 if else 语句 如果是这样 为什么我的代码不起作用 所以这是一个按钮 Calc Input value 指的是文本输入 如果该字段为 0 或空白 我想显示错误消息 在
  • R:如何在没有辅助文件的情况下将光栅写入磁盘?

    我正在使用 R 中的 Raster 包以 ERMapper 格式 ers 编写数据集 但我对生成的 aux xml 辅助文件有问题 我实际上对此不感兴趣 简单的例子 rst lt raster ncols 15000 nrows 10000
  • cuda 中预取(通过 C 代码)

    我正在通过 C 代码在 CUDA Fermi GPU 中进行数据预取 Cuda 参考手册讨论了 ptx 级别代码的预取 而不是 C 级别代码的预取 任何人都可以向我提供一些有关通过 cuda 代码 cu 文件 预取的文档或内容吗 任何帮助
  • 使用 fputs() 将整数写入文件

    不可能做类似的事情fputs 4 fptOut 因为 fputs 不喜欢整数 我该如何解决这个问题 Doing fputs 4 fptOut 不是一个选项 因为我正在使用计数器值 关于什么 fprintf fptOut d yourCoun
  • 比较两个对象数组并检查它们是否具有共同元素

    如何在 MongoDB 中执行返回 id 的查询FirstArray and SecondArray 名称 字段中有共同的元素吗 这是集合结构 id ObjectId 58b8d9e3b2b4e07bff8feed5 FirstArray
  • 如何在 SwiftUI 中随时从子视图作为父视图访问数据?

    我是 SwiftUI 的新手 并且了解我可能需要以某种方式实现 EnvironmentObject 但我不确定在这种情况下如何实现 这是Trade class class Trade var teamsSelected Team init