Reputation: 1
I am updating my State variable with a Binding from another View, I have some code in didSet of my State, it would fired when I do set value from State, but not from Binding, for this reason I have to give a didSet to Binding of this State, which is not logical for me, Binding should Bind but it makes own version of that value with this advantage of updating State as well, I was wandering if it is a bug or it should be in this way! I mean I am expecting reference type behaviour in term of State-Binding, but with this down code, it shows more like Value type! Why this is happening? I was expecting didSet of State get fired even update coming from Binding!
import SwiftUI
struct ContentView: View {
@State var someProperty: String = "Empty string!" {
didSet(oldValue) {
print("State didSet → " + someProperty)
}
}
var body: some View {
Text(someProperty)
.padding()
ButtonView(someProperty: $someProperty)
}
}
struct ButtonView: View {
@Binding var someProperty: String {
didSet(oldValue) {
print("Binding didSet → " + someProperty)
}
}
var body: some View {
Button("update Text") { someProperty = "Hello, world!" }
}
}
update:
struct ContentView: View {
@State private var someProperty: String = "Empty string!" {
didSet(oldValue) {
print("State didSet → " + someProperty)
}
}
var body: some View {
Text(someProperty)
.padding()
Button("update Text") { someProperty = "Hello, world!" }
}
}
Upvotes: 2
Views: 854
Reputation: 54466
didSet
works with @State
only when you modify the @State
directly but not when you change its internal value.
Note that the State
is a wrapper. If you change its internal value (here _someProperty
) using Binding
, then didSet
is not called.
You can use onReceive
or onChange
instead:
import Combine
import SwiftUI
struct ContentView: View {
@State private var someProperty: String = "Empty string!"
var body: some View {
Text(someProperty)
.padding()
// updated on changes only
.onChange(of: someProperty) {
print("State onChange → " + $0)
}
// updated every time
.onReceive(Just(someProperty)) {
print("State onReceive → " + $0)
}
ButtonView(someProperty: $someProperty)
}
}
Upvotes: 5
Reputation: 18914
Use custom binding
var body: some View {
Text(someProperty)
.padding()
ButtonView(someProperty: Binding(
get: { self.someProperty },
set: { self.someProperty = $0 }
))
}
Upvotes: 2