Consider an example like this:
import Combine
let publisher = [1, 2, 3, 4, 5, 6, 7, 3, 5, 6, 7, 8]
.publisher
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
public actor MyActor {
var count: Int = 0
private var subscriptions = Set<AnyCancellable>()
func countThrees() {
observe(number: 3) { myActor in
myActor.count = myActor.count + 1
}
}
func observe(number: Int, action: @escaping (isolated MyActor) -> Void) {
publisher
.filter { $0 == number }
.sink { _ in action(self) }
.store(in: &subscriptions)
}
}
The code seems to work and I can test it like so:
func testIsolatedClosure() async throws {
let a = MyActor()
await a.countThrees()
try await Task.sleep(nanoseconds: 1_000_000_000)
let count = await a.count
XCTAssertEqual(count, 2)
}
But I am confused how it works here:
.sink { _ in action(self) }
How does the sink
function know that it needs to call back on the actor isolation? I would think I would need to do something like this to get it to work:
.sink { _ in
Task {
await action(self)
}
}
But that gives me the warning:
No 'async' operations occur within 'await' expression