Reputation: 1094
I have tried out different ways by which @State can be updated in a SwiftUI view. There are approaches where a state change updates the related view whereas in some it does not.
@State var bodyText: String = "Hello swift"
var body: some View {
Text(bodyText)
.onAppear(perform: triggerTextUpdate)
}
private func triggerTextUpdate() {
DispatchQueue.main.asyncAfter(deadline: .now()+3) {
bodyText = "Hello I am future swift"
}
}
1. @State changed from initializer
@State var bodyText: String = "Hello swift"
init() {
triggerTextUpdate()
}
var body: some View {
Text(bodyText)
}
private func triggerTextUpdate() {
DispatchQueue.main.asyncAfter(deadline: .now()+3) {
bodyText = "Hello I am future swift"
}
}
2. @State changed from mutating function
@State var bodyText: String = "Hello swift"
private let somePublishSubject = PublishSubject<String, Never>()
private var subscriptions = Set<AnyCancellable>()
init() {
setUpBinding()
}
var body: some View {
Text(bodyText)
}
mutating func setUpBinding() {
somePublishSubject.sink { [self] text in
self.bodyText = text
}.store(in: &subscriptions)
}
When the somePublishSubject
gets invoked and alters the bodyText
state, the view does not update.
There is not much documentation on SwiftUI which makes understanding why the view updation and @State
changes become more confusing. Any explanation for this behaviour will be really helpful.
Upvotes: 7
Views: 1440
Reputation: 1934
The doc says it very clearly.
You should only access a state property from inside the view’s body, or from methods called by it. For this reason, declare your state properties as private, to prevent clients of your view from accessing them. It is safe to mutate state properties from any thread.
it means you are not allowed to change state in your init
, or somePublishSubject.sink
Upvotes: 6