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?
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()
}
}
}
}
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.