如何将数据从父模型类传递到 SwiftUI 中的子视图

Posted

技术标签:

【中文标题】如何将数据从父模型类传递到 SwiftUI 中的子视图【英文标题】:How to pass data from a parent model class to a subview in SwiftUI 【发布时间】:2021-06-17 01:34:17 【问题描述】:

我在 ContentView 类中有我的主视图,我在 ContentViewModel 类中进行网络调用,并使用响应更新类调用 User。

我的 ContentView 有几个子视图,例如 HeaderView。当我从 API 响应更新 User 类属性时,我也想更新 HeaderView 中定义的 UI 元素。如何将数据从 ContentViewModel 类传递到我的子视图(HeaderView)?


我可以通过设置 ContentViewModel 类 ObservableObject 来更新非常简单的 ContentView 元素

class ContentViewModel: ObservableObject 

并发布了用户对象

@Published var user = User()

并在我在同一个 ContentViewModel 中收到 API 响应后更新用户的属性

self.user.name = name

我的 ContentView 与其模型类的关系如下所示

@StateObject private var contentViewModel = ContentViewModel()

UI 更新如下

Text("My name \(contentViewModel.user.name)")

这就是 ContentView 的工作场景。但我需要将值传递给 HeaderView()。 我的用户类如下所示

import Foundation

class User 
    var name = ""
// more attributes

【问题讨论】:

你能显示HeaderView的代码吗?也许只使用Binding 【参考方案1】:

这是我经常使用的模式:(注意没有私有变量)

struct ContentView: View 
    @StateObject var contentViewModel = ContentViewModel()
    ...
    var body: some View 
        ...
        HeaderView(contentViewModel: contentViewModel)
    


struct HeaderView: View 
    @ObservedObject var contentViewModel: ContentViewModel

    var body: some View 
        ...
        Text("My name \(contentViewModel.user.name)")
    


struct User 
    var name = ""
// more attributes

您可以使用相同的想法与“.environment(...)”模式将 ContentViewModel 传递给所有子视图。

编辑:正如@Asperi 建议的那样,用户应该成为一个结构。

【讨论】:

不应该HeaderViewStateObjectObservedObject 你应该在HeaderView中使用@ObservedObject,见***.com/questions/62544115/… @workingdog 答案和@Asperi 答案的组合有效。对于我们的主视图在几个子视图中构建的场景,我们没有直接的 UI 重绘属性,我们需要 @Asperi 提供的建议。如果您可以用他的建议更新您的答案(也给予他的信任:)),我可以接受这是正确的答案。 (因为我不能接受一个问题的两个答案:D)。此外,您可以提供.environment(...) 选项作为另一种丰富您的答案的方法。非常感谢。 当您将根“视图模型”传递给“子视图”(HeaderView) 时,子视图不能再用作组件 - 这在很大程度上取决于特定的视图模型。将“子视图状态”传递给子视图将是一种改进。子视图的“动作”(又名意图,又名事件)可以用子视图中的函数实例(回调)来建模。父视图设置子状态和操作功能(并处理从子视图发送的用户操作和其他操作,它只是发送到视图模型)。【参考方案2】:

当我从 API 响应更新用户类属性时,我想更新 UI

无论您如何将模型传递给子视图,它都不会更新,因为您的 User 是一个 ,因此更改其属性不会激活发布(因为已发布的包装器包含引用未更改的用户),因此视图未更新。

相反,您应该将 User 设为结构

struct User 
    var name = ""
// more attributes

或将其设为ObservableObject,同时发布所有需要的属性,并通过引用传递给以常规方式观察它的子视图。

【讨论】:

以上是关于如何将数据从父模型类传递到 SwiftUI 中的子视图的主要内容,如果未能解决你的问题,请参考以下文章

Vue:如何将数据从父组件传递到所需的子组件?

如何将 Angular 5 中的点击数据从父组件传递到子组件?

将数据从模型传递到 SwiftUI 中的视图

Swift - 将数据从父视图控制器传递到子视图控制器

如何在从父组件到子组件的角度5中单击时传递数据?

SwiftUI:如何将 NSManagedObjectContext 传递到多个视图模型中