如何在 SwiftUI 中重置子视图?

2023-12-28

下面是我正在使用的代码的简化版本。但每当我重置键盘()时,它仍然显示以前的键盘。无论如何,当我调用 ResetKeyboard() 时,它会用新的 KeyboardView 替换键盘吗?

struct GameView: View {
    @State var myKeyboard = KeyboardView()

    var body: some View {
        VStack{
            Button("Change Keyboard") {
                myKeyboard.change()
            }


            myKeyboard

            Button("Reset Keyboard") {
                resetKeyboard()
            }
        }
    }

    func resetKeyboard(){
        self.myKeyboard = KeyboardView()
    }
}

SwiftUI 构造一个视图树View对象在body他们的父母。

所以,SwiftUI 得到的是最初的copy(记住,这是一个值类型struct) of myKeyboard,而不是您要更改的副本。

在正常使用情况下,您不会将各种 View 的实例存储为变量(我的意思是,您可以,但您需要深入了解发生了什么)。

您可能想要的是更改驱动子视图的数据。这些数据(应该)存放在哪里?这取决于你想做什么。


在大多数情况下,父级“拥有”状态,即拥有子级所依赖的某些数据的真实来源。然后更改状态并通过其将状态传递给子级就很简单了init:

struct ChildView: View {
   let number: Int

   var body: some View {
      Text("\(number)")
   }
}

struct ParentView: View {
   @State var random: Int = Int.random(1...100)

   var body: some View {
      VStack() {
         ChildView(number: random)
         Button("randomize") { 
            self.random = Int.random(1...100)
         }
      }
   }
}

但是,比如说,父母不想进行随机化——即孩子应该处理它。

正确的方法是为子级创建一个视图模型,父级(或父级自己的视图模型)可以拥有并通过init,然后视图模型将处理随机化的细微差别。

class ChildVM: ObservableObject {
   @Published var random = Int.random(1...100)

   func change() {
      random = Int.random(1...100)
   }
}

父级创建一个实例ChildVM并将其传递给孩子:

struct ParentVuew: View {
   let childVM = ChildVM()

   var body: some View {
      VStack() {
         ChildView(vm: childVm)
         Button("randomize") { 
            self.childVM.change()
         }
      }
   }
}

子视图只是由视图模型驱动:

struct ChildView: View {
   @ObservedObject let vm: ChildVM

   var body: some View {
      Text("\(vm.random)")
   }
}

显然,这是一个可以通过多种方式实现的简化示例。

父母可以通过不同的方式向孩子“发送消息”。

但一般的结论应该是View应该被认为是声明性结构——而不是活的实例——而数据是驱动这些视图变化的因素。您需要决定谁最能拥有真相来源。

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

如何在 SwiftUI 中重置子视图? 的相关文章

随机推荐