updateMessage()
が呼び出されているのを確認できても、ExampleViewのmessage
変数を更新できません。これが、機能していないPlaygroundコードの単純化/複雑化したSwiftUIの例です。 message
varは、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
および@PublishedObject, @ObservedObject
。これらのパブリッシャーの1つが必要なので、ビューは実際に何かを行う必要があることに気づきます。
ボタンを押すたびに新しいExampleView
を描画するか、この場合は@State
ContentView
の変数:
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)
}
}
これはおそらくあなたが望むものではありません。
次に、あなたは使うことができます @Binding これはすでに提案されていました。
そして最後に、あなたは使うことができます ObservableObject @ ObservedObject、@ Published
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
も同様に、変数をトップビューに渡すだけで、ビュー階層の下のすべてがそれを継承します。
うまくいくはずのソリューションの1つですが、みんなが言うように、@Binding
struct ExampleView: View {
var message: String = "Hello"
var body: some View {
Text(self.message)
}
mutating func updateMessage() {
print("updateMessage ran")
message = "Updated"
}
}