Skip to content

Instantly share code, notes, and snippets.

@robertmryan
Last active June 5, 2024 15:45
Show Gist options
  • Select an option

  • Save robertmryan/c1911e7ddfece63edae85c46be1c76c5 to your computer and use it in GitHub Desktop.

Select an option

Save robertmryan/c1911e7ddfece63edae85c46be1c76c5 to your computer and use it in GitHub Desktop.
import SwiftUI
import AsyncAlgorithms
import os.log
private let poi = OSSignposter(subsystem: "MyApp", category: .pointsOfInterest)
typealias AsyncClosure = () async -> Void
struct ExperimentView: View {
@StateObject var viewModel = ExperimentViewModel()
var body: some View {
VStack {
Button("Red") { Task { await viewModel.addRed() } }
Button("Green") { Task { await viewModel.addGreen() } }
Button("Blue") { Task { await viewModel.addBlue() } }
}
.task {
await viewModel.monitorChannel()
}
}
}
@MainActor
class ExperimentViewModel: ObservableObject {
let channel = AsyncChannel<AsyncClosure>()
func monitorChannel() async {
for await block in channel {
await block()
}
}
func addRed() async {
poi.emitEvent(#function)
await channel.send { await self.red() }
}
func addGreen() async {
poi.emitEvent(#function)
await channel.send { await self.green() }
}
func addBlue() async {
poi.emitEvent(#function)
await channel.send { await self.blue() }
}
func red() async {
let state = poi.beginInterval(#function)
defer { poi.endInterval(#function, state) }
try? await Task.sleep(for: .seconds(3))
}
func green() async {
let state = poi.beginInterval(#function)
defer { poi.endInterval(#function, state) }
try? await Task.sleep(for: .seconds(3))
}
func blue() async {
let state = poi.beginInterval(#function)
defer { poi.endInterval(#function, state) }
try? await Task.sleep(for: .seconds(3))
}
}
@robertmryan

robertmryan commented Jan 23, 2024

Copy link
Copy Markdown
Author

Unlike my original answer, this is using standard “Points of Interest” tool, so the graph looks less colorful, but doesn’t require you to install my custom point of interest tool:

CleanShot 2024-01-23 at 08 29 12@2x

But the idea is the same. I rapidly tapped “red”, “green”, and “blue” buttons in succession, repeating the process three times. I then repeated the exercise, but this second time, I dismissed the view in question before it was completed, thereby canceling the channel (and its associated tasks).

@robertmryan

Copy link
Copy Markdown
Author

FWIW, in case anyone is interested in how I generated the multicolored intervals in my original answer, see CustomPointsOfInterest. But it is not immediately relevant to the question at hand, but was merely a nice visual way of associating the red, green, and blue intervals with the associated functions in my original answer. But I have excised it from my MRE above (and the associated repo) for the sake of simplicity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment