[英]Unable to update/modify SwiftUI View's @state var
即使我可以看到正在调用updateMessage()
我也无法更新 ExampleView 的message
updateMessage()
。 这是我的 Playground 代码的简化/复杂 SwiftUI 示例,但它不起作用。 该message
在调用时变种没有更新updateMessage()
因此,UI Text()
也不会更新。
为什么@State var message
没有更新? 更新它的正确方法是什么?
import SwiftUI
import PlaygroundSupport
struct ContentView: View {
let coloredLabel = ExampleView()
var body: some View {
VStack {
coloredLabel
.foregroundColor(Color.red)
.padding()
Button(action: {
self.coloredLabel.updateMessage()
}) {
Text("Press me")
}
}
}
}
struct ExampleView: View {
@State private var message: String = "Hello"
var body: some View {
Text(self.message)
}
func updateMessage() {
print("updateMessage ran") // this prints
self.message = "Updated"
}
}
PlaygroundPage.current.setLiveView(ContentView())
您应该只在它自己的主体块内更改视图的State
。 如果您需要从父视图更改它,您可能希望将值从父视图传递给它并改为Binding
。
struct ContentView: View {
@State private var message = "Hello"
var body: some View {
VStack {
ExampleView(message: $message)
.foregroundColor(Color.red)
.padding()
Button("Press me") {
self.message = "Updated"
}
}
}
}
struct ExampleView: View {
@Binding var message: String
var body: some View {
Text(message)
}
}
如果您需要在ExampleView
封装消息,您可以使用Bool
(或enum
等)代替:
struct ContentView: View {
@State private var updated = false
var body: some View {
VStack {
ExampleView(isUpdated: $updated)
.foregroundColor(Color.red)
.padding()
Button("Press me") {
self.updated = true
}
}
}
}
struct ExampleView: View {
@Binding var isUpdated: Bool
private var message: String { isUpdated ? "Updated" : "Hello" }
var body: some View {
Text(message)
}
}
实际上,该变量确实会更新,但您的 Content 视图并未获知它。 这是发生的事情:
现在,您有不同的选择: @State
、 @Binding
和@PublishedObject, @ObservedObject
@State
、 @Binding
@PublishedObject, @ObservedObject
。 您需要这些发布者之一,因此您的视图实际上会注意到它需要做一些事情。
每次按下按钮时都绘制一个新的ExampleView
,在这种情况下,您可以在ContentView
使用@State
变量:
struct ContentView: View {
@State private var string = "Hello"
var body: some View {
VStack {
ExampleView(message: string)
.foregroundColor(Color.red)
.padding()
Button(action: {
self.string = "Updated"
}) {
Text("Press me")
}
}
}
}
struct ExampleView: View {
var message: String
var body: some View {
Text(self.message)
}
}
这可能不是你想要的。
which was already suggested.接下来,您可以使用已经建议的 。
最后,你可以使用
class ExampleState: ObservableObject {
@Published var message: String = "Hello"
func update() {
message = "Updated"
}
}
struct ContentView: View {
@ObservedObject var state = ExampleState()
var body: some View {
VStack {
ExampleView(state: state)
.foregroundColor(Color.red)
.padding()
Button(action: {
self.state.update()
}) {
Text("Press me")
}
}
}
}
struct ExampleView: View {
@ObservedObject var state: ExampleState
var body: some View {
Text(state.message)
}
}
这说的是: class ExampleState: ObservableObject
- 这个类已经发布了可以观察的变量
恢复(这就是我的理解):
ContentView
和ExampleView
:如果state.message
( state
发布的任何值)发生变化,你需要重绘你的身体”ExampleState
:更新您的消息变量后,发布新值!” 最后 - 为了完成 - 还有@EnvironmentObject
,这样你只需要将变量传递给顶视图,视图层次结构中的所有内容都会继承它。
应该可行的解决方案之一,但正如人们所说,您可以使用@Binding
struct ExampleView: View {
var message: String = "Hello"
var body: some View {
Text(self.message)
}
mutating func updateMessage() {
print("updateMessage ran")
message = "Updated"
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.