繁体   English   中英

无法更新/修改 SwiftUI 视图的 @state var

[英]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 视图并未获知它。 这是发生的事情:

  • with an 内容查看被调用,它与初始化
  • 你按下 ContentView 中的按钮
  • self.coloredLabel.updateMessage() 被调用
  • 消息被打印
  • 变量 self.coloredLabel.message 被修改
  • ContentView 不会被重绘,因为它没有收到有关更改的通知
  • inside your Stack doesn't get updated更具体地说,您 Stack 中的不会更新

现在,您有不同的选择: @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 - 这个类已经发布了可以观察的变量

恢复(这就是我的理解):

  • “嘿, ContentViewExampleView :如果state.messagestate发布的任何值)发生变化,你需要重绘你的身体”
  • “和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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM