我想将View
存储为变量供以后使用,同时将View
传递给某些Bindings
。
这是我尝试过的:
struct Parent: View {
@State var title: String? = ""
var child: Child!
init() {
self.child = Child(title: self.$title)
}
var body: some View {
VStack {
child
//...
Button(action: {
self.child.f()
}) {
//...
}
}
}
}
struct Child: View {
@Binding var title: String?
func f() {
// complex work from which results a string
self.title = <that string>
}
var body: some View {
// ...
}
}
它可以正确编译,并且View
可以按预期显示,但是当从子级更新从父级传递来的Binding
时,该变量永远不会更新。您甚至可以(从孩子那里)做类似的事情:
self.title = "something"
print(self.title) // prints the previous value, in this case nil
我不知道这是否是一个错误,但是直接在body
属性中初始化子级可以解决问题。但是,我需要该孩子作为属性来访问其方法。
答案 0 :(得分:0)
这与SwiftUI框架的设计背道而驰。您不应具有任何持久视图来调用方法。相反,视图会根据需要创建并显示,以响应您的应用程序状态更改。
将数据封装在ObservableObject
模型中,并实现需要在该模型上调用的所有方法。
更新
在Child
中定义这样的函数很好,但是您只能在Child
结构定义中调用它。例如,如果您的子视图包含一个按钮,则该按钮可以调用子视图的实例方法。例如,
struct Parent: View {
@State private var number = 1
var body: some View {
VStack {
Text("\(number)")
Child(number: $number)
}
}
}
struct Child: View {
@Binding var number: Int
func double() {
number *= 2
}
var body: some View {
HStack {
Button(action: {
self.double()
}) {
Text("Double")
}
}
}
}
但是您不会尝试从子结构的外部调用double()
。如果需要一个可以全局调用的函数,请将其放在数据模型中。如果函数调用正在发出网络请求,则尤其如此,因为即使由于布局更改而重新创建模型,模型也会停留在子视图之外。
class NumberModel: ObservableObject {
@Published var number = 1
func double() {
number *= 2
}
}
struct Parent: View {
@ObservedObject var model = NumberModel()
var body: some View {
VStack {
Text("\(model.number)")
Button(action: {
self.model.double()
}) {
Text("Double from Parent")
}
Child(model: model)
}
}
}
struct Child: View {
@ObservedObject var model: NumberModel
var body: some View {
HStack {
Button(action: {
self.model.double()
}) {
Text("Double from Child")
}
}
}
}
答案 1 :(得分:0)
如果您想为孩子更改“父母”的某些内容,则绑定是正确的方法。如果那很复杂,则必须使用DataModel。
struct Parent: View {
@State var title: String? = ""
var body: some View {
VStack {
Child(title: $title)
Button(action: {
self.title = "something"
}) {
Text("click me")
}
}
}
}
struct Child: View {
@Binding var title: String?
var body: some View {
Text(title ?? "")
}
}