我必须在Swiftui中使用可观察的对象吗?

发布于 2025-02-10 03:47:22 字数 1534 浏览 1 评论 0原文

我想使用struct而不是class作为我的view的状态,并且您可能知道,observerableObject < /code>是一个只能符合的协议。

是否有将我的结构包裹在viewmodel或其他类似类型的对象中?如果我不这样做会怎样?

现在的样子:

import Foundation
import SwiftUI

struct Object3D {
    var x : Int
    var y : Int
    var z : Int
    var visible : Bool
}

struct NumberView<Number : Strideable> : View {
    var label : String
    @State var number : Number
    
    var body : some View {
        HStack {
            TextField(
                self.label,
                value: self.$number,
                formatter: NumberFormatter()
            )
            Stepper("", value: self.$number)
                .labelsHidden()
        }
    }
}

struct ObjectInspector : View {
    @State var object : Object3D
    
    var body : some View {
        VStack {
            Form {
                Toggle("Visible", isOn: $object.visible)
            }
            Divider()
            Form {
                HStack {
                    NumberView(label: "X:", number: object.x)
                    NumberView(label: "Y:", number: object.y)
                    NumberView(label: "Z:", number: object.z)
                }
            }
        }
        .padding()
    }
}

struct ObjectInspector_Previews: PreviewProvider {
    static var previews: some View {
        ObjectInspector(object: Object3D(x: 0, y: 0, z: 0, visible: true))
    }
}

I would like to use a struct instead of a class as a state for my View, and as you may know, ObservableObject is a protocol only classes can conform to.

Do I have to wrap my struct in a ViewModel or some other similar type of object ? What happens if I don't ?

A sample on what that looks like now :

import Foundation
import SwiftUI

struct Object3D {
    var x : Int
    var y : Int
    var z : Int
    var visible : Bool
}

struct NumberView<Number : Strideable> : View {
    var label : String
    @State var number : Number
    
    var body : some View {
        HStack {
            TextField(
                self.label,
                value: self.$number,
                formatter: NumberFormatter()
            )
            Stepper("", value: self.$number)
                .labelsHidden()
        }
    }
}

struct ObjectInspector : View {
    @State var object : Object3D
    
    var body : some View {
        VStack {
            Form {
                Toggle("Visible", isOn: $object.visible)
            }
            Divider()
            Form {
                HStack {
                    NumberView(label: "X:", number: object.x)
                    NumberView(label: "Y:", number: object.y)
                    NumberView(label: "Z:", number: object.z)
                }
            }
        }
        .padding()
    }
}

struct ObjectInspector_Previews: PreviewProvider {
    static var previews: some View {
        ObjectInspector(object: Object3D(x: 0, y: 0, z: 0, visible: true))
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

jJeQQOZ5 2025-02-17 03:47:22

您不必使用@ObseverObject来确保对模型对象的更新正在更新视图。

如果要使用struct作为模型对象,则可以使用@State,并且您的视图将在您的@State < < <代码>结构已更新。

每当您的模型对象更新时,您可以使用许多不同的属性包装器来更新SwiftUi视图。您可以将值和参考类型同时用作模型对象,但是,根据您的选择,您必须使用不同的属性包装器。

@State只能在价值类型上使用,@State属性只能从视图内部进行更新(因此,它们必须为private) 。

@observedObject(以及所有其他...对象属性包装器,例如@environmentObject@stateObject),只能与符合的类一起使用到observableObject。如果您想能够从视图内部和外部更新模型对象,则必须使用observableObject与适当的属性包装器一致类型,您不能使用@State在这种情况下。

因此,请考虑可以从view内部或视图外部捕获的用户输入来更新您的模型对象的源需要价值或参考语义,并为您的数据模型做出适当的选择。

有关@obseverobject@stateObject之间的差异的更多信息,请参见 SwiftUI中的观察者和StateObject之间有什么区别

You don't have to use @ObservedObject to ensure that updates to your model object are updating your view.

If you want to use a struct as your model object, you can use @State and your view will be updated correctly whenever your @State struct is updated.

There are lots of different property wrappers that you can use to update your SwiftUI views whenever your model object is updated. You can use both value and reference types as your model objects, however, depending on your choice, you have to use different property wrappers.

@State can only be used on value types and @State properties can only be updated from inside the view itself (hence they must be private).

@ObservedObject (and all other ...Object property wrappers, such as @EnvironmentObject and @StateObject) can only be used with classes that conform to ObservableObject. If you want to be able to update your model objects from both inside and outside your view, you must use an ObservableObject conformant type with the appropriate property wrapper, you cannot use @State in this case.

So think about what sources your model objects can be updated from (only from user input captured directly inside your View or from outside the view as well - such as from other views or from the network), whether you need value or reference semantics and make the appropriate choice for your data model accordingly.

For more information on the differences between @ObservedObject and @StateObject, see What is the difference between ObservedObject and StateObject in SwiftUI.

心奴独伤 2025-02-17 03:47:22

我想使用struct而不是类作为我的视图的状态,众所周知,可观察的对象是一个协议,只有类才能符合。

通常在应用程序的任何部分中共享模型,因此他们一直在查看相同的数据。为此,您需要一个参考类型(即类),以便每个人都共享模型的单个实例。如果您使用 value Type (即结构),则每次将其分配给某些东西时,您的模型都会被复制。为了进行该工作,您需要将更新的信息复制回该功能时,只要您完成它的更新,然后安排可能使用它来获取更新副本的应用程序的其他部分。共享一个实例通常比管理这种更新要容易得多,更安全。

i 是否有将我的结构包裹在视图模型或其他类似类型的对象中?如果我不这样做会怎样?

这是您的代码 - 您可以做任何喜欢的事情。 ObservableObject提供了一个很好的机制,可以传达您的模型已更改为程序的其他部分的事实。这并不是唯一的方法,但这是Swiftui这样做的方式,因此,如果您走了另一条路线,您将在Swiftui内置的大量支持下丢失。

I would like to use a struct instead of a class as a state for my View, and as you may know, ObservableObject is a protocol only classes can conform to.

A model is usually shared among whichever parts of the app need it, so that they're all looking at the same data all the time. For that, you want a reference type (i.e. a class), so that everybody shares a single instance of the model. If you use a value type (i.e. a struct), your model will be copied each time you assign it to something. To make that work, you'd need to copy the updated info back to wherever it belongs whenever you finish updating it, and then arrange for every other part of the app that might use it to get an updated copy. It's usually a whole lot easier and safer to share one instance than to manage that sort of updating.

Do I have to wrap my struct in a ViewModel or some other similar type of object ? What happens if I don't ?

It's your code -- you can do whatever you like. ObservableObject provides a nice mechanism for communicating the fact that your model has changed to other parts of your program. It's not the only possible way to do that, but it's the way that SwiftUI does it, so if you go another route you're going to lose out on a lot of support that's built into SwiftUI.

千纸鹤 2025-02-17 03:47:22

View已经是一个结构,它不能是类。它保存了SwiftUi差异以更新屏幕上的实际uiview nsview s的数据。它使用@State@binding属性包装器使其表现得像一类上次。您可以将VAR的重构组重构为其自己的可测试结构,并包括突变func s。

通常,您通常只需要一个observableObject,如果您使用的是组合,则是组合框架的一部分。

我建议观看通过SwiftUi WWDC 2019的数据流 有更多详细信息。

The View is a struct already, it cannot be a class. It holds the data that SwiftUI diffs to update the actual UIViews and NSViews on screen. It uses the @State and @Binding property wrappers to make it behave like a class, i.e. so when the hierarchy of View structs is recreated they are given back their property values from last time. You can refactor groups of vars into their own testable struct and include mutating funcs.

You usually only need an ObservableObject if you are using Combine, it's part of the Combine framework.

I recommend watching Data Flow through SwiftUI WWDC 2019 for more detail.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文