In this demo, you’ll update TheMet app to use an actor to isolate data and avoid data races.
Open TheMet app in the Starter folder and run the app on the simulator.
Now that you know the app is working, check out the warning that appears in the warning tab.
Xcode is warning you that a background thread is updating the objects property.
You can see this happening by looking at line 62, where you append a newly fetched object to objects. This line runs inside an asynchronous function, which is called by a task when the app launches.
You can fix this warning by ensuring TheMetStore is annotated with MainActor. Do that now:
@MainActor class TheMetStore: ObservableObject {
@Published var objects: [Object] = []
let service = TheMetService()
let maxIndex: Int
With the annotation added, this tells Swift and Swift compiler this class needs to perform work on the main queue so it can update the UI. Our asynchronous code in the class will still work asynchronously, because it uses a TaskGroup.
Run the app again. You’ll notice the app continues to run as before. This time though, the warning no longer appears!
However, you may see this new warning:
Passing argument of non-sendable type ‘ThrowingTaskGroup<Object?, any Error>’ outside of main actor-isolated context may introduce data races
This is because Swift thinks that the call to taskGroup.reduce may possibly be executed on another context… However, it’s actually not.
To clear up Swift’s confusion, you can rewrite this code to use a for loop instead:
var results = [Object]()
for try await result in taskGroup {
if let object = result {
results.append(object)
}
}
return results
Build and run, and you’ll now see that the project is warning free.
Nice, with just a few lines of code, you’ve updated TheMetStore to use Actors!