Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift Concurrency - Why my Task didn't inherit the parent Task's executor and priority

When creating Task A from Task B, I thought Task A will inherit from Task B. But when running the following code I created, why did line 14 printed debug 4: <NSThread: 0x30361a300>{number = 6, name = (null)}. Why it isn't main thread, just like the other prints?

enter image description here

Here's the code for anyone who wants to run locally:

struct Test {
    func test() {
        print("debug 3:", Thread.current)
        Task {
            print("debug 4:", Thread.current)
        }
    }
}

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        Task { @MainActor in
            print("debug 1:", Thread.current)
            Task {
                print("debug 2:", Thread.current)
                Test().test()
            }
        }
    }
}
like image 769
Shuaiqing Luo Avatar asked Oct 28 '25 02:10

Shuaiqing Luo


1 Answers

The function test is not actor-isolated. Thus, its Task {…} is not actor-isolated either. (If test was actor-isolated, then its Task {…} would be a top level task on the same actor. But test not actor-isolated, so that is moot.)

In Swift concurrency, a function’s isolation is either explicitly defined or inherited from the type in which it is defined, if any, but it does not “inherit” it from the caller.


While the above answers the original question, it should be noted that Swift 6.2 introduces a new wrinkle: As part of the broader “Approachable Concurrency” initiative, there is a new “Default Actor Isolation” build setting. Legacy projects will follow the historical pattern of a “Default Actor Isolation” setting of “nonisolated”, but new Xcode 26 projects will default to “MainActor”. Obviously, if you use a “Default Actor Isolation” of “MainActor”, then Test will be isolated to the main actor, and then the “debug 4” will obviously run on the main actor, too.

Also, above I mentioned how nonisolated functions do not inherit the isolation of the caller: The exception to this rule in Swift 6.2’s “Approachable Concurrency” is nonisolated async functions, which will do so (unless explicitly marked with @concurrent). But this question was about calling a synchronous method, so this caveat is not immediately relevant, either.

For more information about this new paradigm, see WWDC 2025’s Embracing Swift concurrency.

like image 75
Rob Avatar answered Oct 30 '25 15:10

Rob



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!