I'm waking up this year-old thread because I have the same question. I'm struggling with how to implement an actor property that can be monitored by subscribers, without resorting to the obsolete(?) register-a-callback-function pattern.
Problem statement: I have an actor that manages a network connection of some sort. It has a status property, an enum with cases like connecting, connected, stopped, etc. Clients [plural!] should be able to monitor this property reactively.
So I expose another property statusStream: any AsyncSequence<Status,Never>. Internally this is an AsyncChannel<Status> kept in a stored property, which I send() status changes to.
(BTW, AsyncStream has an API that's completely unsuited to this usage, as it assumes that all the items will be produced synchronously from within a closure. The docs do say that the continuation can escape the closure, but you have to do this by storing it in a captured variable. This API makes no sense to me at all. Fortunately AsyncChannel is friendlier.)
Problem 1: AsyncSequence is not Sendable(!), and an actor can't expose non-Sendable var properties. This seems like a weird omission for a protocol whose entire purpose is to bridge between tasks.
Workaround: Change the property type to any AsyncSequence<Status,Never> & Sendable.
Problem 2: This works great until I add a second observer/iterator. Now neither observer gets all the status changes, in fact each change is sent to only one of them. This seems to be an undocumented limitation of AsyncChannel: an item pushed to it is just passed to a single iterator, whichever one calls/called next first. This makes it useless for the observer pattern!
I've looked through the other tools in swift-async-algorithms but AFAICT none of them support multiple iterators. The documentation is pretty limited so I may be missing something.
[rant]IMO this is a serious design flaw in AsyncSequence: the ambiguity about what multiple iterators do. I know it inherits this from Sequence, which explicitly leaves it undefined what happens if you iterate it multiple times; but in a synchronous sequence this feels more intuitive, plus we have a broader protocol Collection for things that support multiple iteration. In a concurrent system one consumer of an async sequence doesn't really know whether there's some other consumer out there iterating it too. A single-iterator constraint would work much better with an API like Go's channels, where the factory function creates a paired producer and a consumer at the same time.[/rant]
Update: I forgot to add that @Observable is apparently useless for this because it's incompatible with Sendable; at least, I haven't been able to get them to work together.