I'm in the process of converting my code to using Swift concurrency and I'm running into an issue with Actor which I don't know how to fix it correctly.
Here is a simple actor:
actor MyActor {
private var count = 0
func increase() {
count += 1
}
}
In other places where I need to update the actor, I have to call its functions in concurrency context:
Task {
await myActor.increase()
}
That's good. But what I don't understand is if the actor return the increase
function as a closure like this:
actor MyActor {
private var count = 0
func increase() -> () -> Void {
{
print("START")
self.count += 1
print("END")
}
}
}
In other places, I can get a reference to the returned closure and call it freely in non-concurrency context:
class ViewController: UIViewController {
let actor = MyActor()
var increase: (() -> Void)?
override func viewDidLoad() {
super.viewDidLoad()
Task {
increase = await actor.increase()
}
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
let increase = self.increase
DispatchQueue.concurrentPerform(iterations: 100) { _ in
increase?()
}
}
}
}
The above code print this to the output:
START
START
START
START
START
END
END
START
START
...
I'm not sure if I understand or use Actor correctly. Actor protects its state from data races, but in this case, it does not prevent that. Is it correct behavior? Is there a way to fix it?