Hello and thank you for your reply.
The problem is that I simply have not found a working example for what I am actually trying to do.
In one of my tests I also tried to simulate a long running operation with
await Task.sleep(...)
and it worked. But as soon as I want to run some other code (that by default is not await able because it is not async), I don't know what to do.
That's why I thought that putting the code into an async function so I could use await would be the correct move.
I have created another small demo. In it, a 512 MB file is written to a rather old (and slow) external hard disk:
import Observation
import AppKit
@Observable
final class Model : Sendable
{
@MainActor var controller = AsyncController()
init()
{
}
}
@Observable // Too good to not use.
@MainActor // Required for Observable to work? Can't get it to work without it.
class AsyncController
{
private(set) var isWorking = false
public func heavyWork() async throws {
self.isWorking = true
do {
try await self.save()
}
catch {
Swift.print(error.localizedDescription)
}
self.isWorking = false
}
func save() async throws {
let task = Task {
let data = Data(count: 512 * 1024 * 1024)
let url = URL(fileURLWithPath: "/Volumes/LaCie/out.bin")
try data.write(to: url)
}
return try await task.value
}
}
In this example, the Observable property works fine. As soon as I click the button, the ProgressView is shown. However, the GUI is unresponsive (we are using the Main Actor, so this is to be expected I guess, but I created a new Task so that's what I don't understand).
I also don't see why this should be done in a separate Task, I am already using a Task when clicking the button:
func save() throws {
let data = Data(count: 512 * 1024 * 1024)
let url = URL(fileURLWithPath: "/Volumes/LaCie/out.bin")
try data.write(to: url)
}
So my next best guess was to simply remove the @MainActor from the AsyncController to get this thing off the main thread:
@Observable
class AsyncController
{
}
But now the compiler complains:
Button("Write") {
Task {
try await self.model.controller.heavyWork() // Error: Sending 'self.model.controller' risks causing data races
}
}
Regards,
Sascha
Topic:
Programming Languages
SubTopic:
Swift
Tags: