After going through the material in Chapter 9 I was curious if the example of using the AsyncStream in the global actor was the correct approach ? Doing this required extra “setup” and some boilerplate code it seems, wouldn’t it be more concise to use @Published here since the we are tying the updated value to the UI anyway? I’m trying to understand if there is some advantage of one or the other.
// ImageLoader
@MainActor @Published var testCount: Int = 0
func incrementTestCount() async {
await MainActor.run { testCount += 1 }
}
// BotomToolBar
@ObservedObject var testVar = ImageDatabase.shared.imageLoader
....
Text("Access: \(onDiskAccessCount) from disk, \(testVar.testCount) in memory")
vs
\\ ImageLoader
@MainActor private(set) var inMemoryAccess: AsyncStream<Int>?
private var inMemoryAccessContinuation: AsyncStream<Int>.Continuation?
private var inMemoryAccessCounter = 0 {
didSet { inMemoryAccessContinuation?.yield(inMemoryAccessCounter) }
}
deinit {
inMemoryAccessContinuation?.finish()
}
func setup() async {
let accessStream = AsyncStream<Int> { continuation in
inMemoryAccessContinuation = continuation
}
await MainActor.run { inMemoryAccess = accessStream }
}
// BotomToolBar
@State var inMemoryAccessCount = 0
Text("Access: \(onDiskAccessCount) from disk, \(inMemoryAccessCount) in memory")
.task {
guard let memoryAccessSequence =
ImageDatabase.shared.imageLoader.inMemoryAccess else {
return
}
for await count in memoryAccessSequence {
inMemoryAccessCount = count
}
}