gpt4 book ai didi

ios - 父 View 中的状态更改创建子 ViewModel 的新实例

转载 作者:行者123 更新时间:2023-12-01 16:11:11 26 4
gpt4 key购买 nike

问题
当一个 State如果父 View 中的变量发生变化,SwiftUI 将重绘 subview 并因此再次调用它们的构造函数。
考虑以下 View :

struct Parent: View {
@ObservedObject var viewModel: ParentViewModel

var body: some View {
VStack {
Child(viewModel: ChildViewModel())
}
}
}
Parent 中的任何状态更改 View (例如 Published 在其 ViewModel 中更改的变量)可能会导致 Child要重绘的 View ,导致其 viewModel属性来接收 ChildViewModel 的新实例.
期望与现实
当一个 subview 被重绘时,我希望它仍然能反射(reflect)它以前的状态,但是因为构造函数被再次调用 ViewModel 的新实例。 , 不是这种情况。
我试过的
让我先强调我们使用 SwiftUI 1.0 ,所以使用 @StateObject属性包装器不是一个选项。
我们尝试使用 ViewModelProvider将某种类型的 ViewModel 缓存更长时间的类,以便某个 ViewModel 的连续初始化将返回相同的实例。如果一次只能有一个 ViewModel(因此也就是 View)的一个实例,这将非常有效。但是,一旦您添加了可以导航到同一 View 的新实例的 View (添加了存在多个相同类型的 View 模型的要求),这就会分崩离析。
关于使上述模式起作用,我们有一些额外的想法,但我无法摆脱这种感觉,应该有更好的方法来做到这一点,而无需跳过箍。
代码
设置 Example作为 rootView您的 SceneDelegate ,再加上对按钮的猛烈敲击,应该会触发打印语句,这些语句应该会不时地(甚至不可预测地)显示 ChildViewModel 的不同实例用来。
struct Example: View {
@State var selection = 0
var body: some View {
VStack {
Button("Tapped \(selection) times") {
self.selection += 1
}

ChildView(viewModel: ChildViewModel())
ChildView(viewModel: ChildViewModel())
}
}
}

struct ChildView: View {
@ObservedObject var viewModel: ChildViewModel
var body: some View {
Text("Child")
}
}

class ChildViewModel: ObservableObject {
init() {
withUnsafePointer(to: self) {
print($0)
}
}
}

最佳答案

SwiftUI 2
使用 StateObject - 它只创建一次:

struct ExampleView: View {
@State var selection = 0

var body: some View {
VStack {
Button("Tapped \(selection) times") {
self.selection += 1
}

ChildView() // don't pass the ViewModel
ChildView()
}
}
}

struct ChildView: View {
@StateObject var viewModel = ChildViewModel() // create here

var body: some View {
Text("Child")
}
}
另见:
  • What is the difference between ObservedObject and StateObject in SwiftUI

  • SwiftUI 1
    您可能需要使用 @EnvironmentObject反而。
    SceneDelegate :
    let viewModel = ChildViewModel()
    ExampleView()
    .environmentObject(viewModel)
    ChildView :
    struct ChildView: View {
    @EnvironmentObject var viewModel: ChildViewModel // automatically injected

    var body: some View {
    Text("Child")
    }
    }

    或者,您可以使用结构而不是类:
    struct ChildViewModel { ... }

    struct ChildView: View {
    @State var viewModel = ChildViewModel() // mark as `@State`

    var body: some View {
    Text("Child")
    }
    }

    关于ios - 父 View 中的状态更改创建子 ViewModel 的新实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63952147/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com