Swift task is not running on main actor as expected

Viewed 779

I have the following code in a simple Mac test project:

@main
class AppDelegate: NSObject, NSApplicationDelegate {
  func applicationDidFinishLaunching(_ aNotification: Notification) {
    print("are we initially on the main thread: \(Thread.isMainThread)")

    Task {
      print("is new task on main thread: \(Thread.isMainThread)")
    }
  }
}

In the Swift language guide, I see the following:

To create an unstructured task that runs on the current actor, call the Task.init(priority:operation:) initializer. To create an unstructured task that’s not part of the current actor, known more specifically as a detached task, call the Task.detached(priority:operation:) class method.

So since the AppDelegate code is running on the main actor and I'm creating a normal (i.e. non-detached) task, I'd expect its child task to also run on the main actor.

But that's not what happens when I run this test app:

are we initially on the main thread: true
is new task on main thread: false

Based on what I've read about Swift concurrency, I expected the new task to be scheduled and run on the main actor and that Thread.isMainThread would therefore be true inside that task.

Why is that not the case?

1 Answers

The important distinction to be made here just running code on main thread doesn't mean code is running on MainActor. To have your method always run on MainActor you can make the applicationDidFinishLaunching method isolated to MainActor with @MainActor attribute. In swift concurrency, if you make methods/properties isolated to an actor any Task you create inside them with Task.init will also inherit the actor context. Currently you don't have your actor isolation specified and hence seeing this behavior.

Related