I have this sample code
import SwiftUI
struct ContentView: View {
var body: some View {
ParentView()
}
}
struct ParentView: View {
@State var id = 0
var body: some View {
VStack {
Button {
id+=1
} label: {
Text("update id by 1")
}
TestView(id: id)
}
}
}
struct TestView: View {
var sequence = DoubleGenerator()
let id: Int
var body: some View {
VStack {
Button {
sequence.next()
} label: {
Text("print next number").background(content: {
Color.green
})
}
Text("current id is \(id)")
}.task {
for await number in sequence.stream {
print("next number is \(number)")
}
}
}
}
final class DoubleGenerator {
private var current = 1
private let continuation: AsyncStream<Int>.Continuation
let stream: AsyncStream<Int>
init() {
var cont: AsyncStream<Int>.Continuation!
self.stream = AsyncStream { cont = $0 }
self.continuation = cont
}
func next() {
guard current >= 0 else {
continuation.finish()
return
}
continuation.yield(current)
current &*= 2
}
}
the print statement is only ever executed if I don't click on the update id by 1 button. If i click on that button, and then hit the print next number button, the print statement doesn't print in the xcode console. I'm thinking it is because the change in id triggered the view's init function to be called, resetting the sequence property and so subsequent clicks to the print next number button is triggering the new version of sequence but the task is still referring its previous version.
Is this expected behaviour? Why in onChange and Button, the reference to the properties is always up to date but in .task it is not?