The best way to tackle this depends on the nature of your dot generation code. There are two possibilities:
Let me talk about each in turn.
In the first case, you could have the main actor start an async function to generate the next group of results based on the saved state. That function then returns both the group of results and an updated saved state. The main actor then applies the group of results and, if it so desires, calls the async function again to generate the next group of results.
So, the async function might look like this:
func nextGroupOfResults(inputs: Inputs, state: MyState?) async -> ([ResultGroup], MyState) {
…
}
struct Inputs { }
struct ResultGroup { }
struct MyState { }
and you might call it like this:
while true {
let inputs = Inputs()
let (resultGroup, newState) = await nextGroupOfResults(inputs: inputs, state: self.state)
… apply result group …
self.state = newState
}
If the dot generation is unable to save its state easily, you can switch to a generation model. In that case you might have a routine like this:
func results(for inputs: Inputs) -> AsyncStream<ResultGroup> {
…
}
struct Inputs { }
struct ResultGroup { }
and then your main actor task would iterate over the result groups like this:
let inputs = Inputs()
for await resultGroup in results(for: inputs) {
… apply result group …
}
That raises the question of what to put in results(for:)
. Here’s how you might do that:
func results(for inputs: Inputs) -> AsyncStream<ResultGroup> {
let (stream, continuation) = AsyncStream.makeStream(of: ResultGroup.self, bufferingPolicy: .unbounded)
Task {
await generateResultGroups(continuation: continuation)
}
return stream
}
func generateResultGroups(continuation: AsyncStream<ResultGroup>.Continuation) async {
… call `continuation.yield(_:)` to return a result group …
… or `continuation.finish()` to be done …
}
The tricky back of this is flow control. If the generateResultGroups(…)
routine can create result groups faster than the main actor can display them, a lot of data can back up in the stream. It’s possible to solve that, but it’s definitely more challenging.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"