Search code examples
swiftconcurrencytaskswift-playground

The behavior of Task seems to differ in Playground environments


In an actual app project, when running the following code, the print statements occur in the order of 1->3->2:

var body: some View {
    Text
    .onAppear {
        print("1")
        Task {
            print("2")
        }
        print("3")
    }
}

However, when executing the equivalent code in Playground, the print statements occur in the order of 1->2->3:

print("1")
Task {
    print("2")
}
print("3")

After conducting several tests in the Playground environment, I observed that running the function inside Task on the mainActor or lowering the priority of the Task significantly (e.g., .background) results in order of 1->3->2:

print("1")
Task { @MainActor in
    print("2")
}
print("3")

// or
print("1")
Task(priority: .background) {
    print("2")
}
print("3")

However, without these additional configuration, I believe that the print order in Playground also should be 1->3->2.

Could you please explain why in Playground the execution order is 1->2->3?


Solution

  • Old version

    It's because in app project your code really starts with something like this:

    @main // Magic here!
    struct ExampleSwiftUIApp: App {

    Updated

    As @Rob points out for an actual app project:

    The main actor isolation stems more directly from the body of the View

    Standing point

    So Task in app project runs on behalf of the current actor (which is main here). So code executes like on main queue. Main queue is serial so order 1->3->2 is guaranteed in app example.

    Now let's look at in-Playground-example. Here you are creating task without actor. Task without actor runs simultaneously with base flow of code. In your sample base flow is print("3"). And, yes, print("3") runs on main thread. But. There is no main actor and so I believe that in Playground

    Task {
        print("2")
    }
    

    produces detached task. So order of execution 2 vs 3 is not guaranteed and may depends on priorities, number of free CPU cores, etc.