Good article.
Don’t quite get what you’re trying to say in the last question part though.
The last question for you: which text will be displayed if inside
onAppear
we setself.value = "abc"
?
I can’t set self.value in the onAppear handler as there’s nothing named “value” in the View. ;)
I can’t set the value in the publisher, as it’s been erased.
I can do the following, setting the value in the parent…
struct TestView: View {
let publisher = CurrentValueSubject<String, Never>("") // 2
var body: some View {
MyView(publisher: publisher.eraseToAnyPublisher())
.onAppear {
self.publisher.value = "abc"
}
}
}struct MyView: View {
let publisher: AnyPublisher<String, Never>
@State var text: String = ""
@State var didAppear: Bool = false
var body: some View {
Text(text)
.onAppear {
self.didAppear = true
}
.onReceive(publisher) {
print("onReceive = '\($0)'")
self.text = $0
}
}
}
But when I do that I get the following output, which is pretty much what I’d expect. The first value from the initialization state, the second value from the onAppear updated state.
onReceive = ''
onReceive = 'abc'
Similarly, if I collapse the example and do the following…
struct MyView: View {
let publisher = CurrentValueSubject<String, Never>("")
@State var text: String = ""
var body: some View {
Text(text)
.onAppear {
self.publisher.value = "abc"
}
.onReceive(publisher) {
print("onReceive = '\($0)'")
self.text = $0
}
}
}
I still get the output shown above.
onReceive = ''
onReceive = 'abc'
Which is what I’d expect.
Finally, I don’t quite get the state GCD behavior either. Consider…
struct MyView3: View {
@State var text: String = "123"
var body: some View {
Text(text)
.onAppear {
self.text = "abc"
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
print(self.text)
self.text = "xyz"
}
}
}
}
Which also works as I’d expect, printing “abc” before updating the view to display “xyz”. And the GCD behavior is pretty much required if you’re going to any kind of async API requests.
I think the key is that a State variable would need to maintain state for as long as its view is in the view hierarchy.
But instantiate a view that’s not coupled to a view hierarchy, as shown in your example, and all bets are off.