Swift中ViewController内闭包是否需添加@MainActor in?
关于Swift代码中@MainActor的疑问解答
问题代码回顾
func connectVCAndVM() { // Setting up a closure to be called when data in the viewModel changes viewModel.dataChanged = { [weak self] in Task { @MainActor in // Reloading the tableView when data changes self?.tableView.reloadData() } } }
核心问题解答
1. 此处是否需要添加@MainActor in?
需要。tableView.reloadData()属于UI操作,必须在主线程执行,但viewModel.dataChanged闭包的执行线程是不确定的——如果ViewModel在后台线程更新数据并触发这个闭包,闭包默认会在后台线程运行。此时若不加@MainActor in,Task会继承当前的后台线程上下文,导致UI操作在后台执行,引发崩溃或UI异常。显式标注@MainActor in能强制Task内的代码切换到主线程执行。
2. 若Task写在ViewController内,是否会因上下文继承自动在主线程执行?
不一定,关键看闭包的执行上下文,而非闭包的定义位置:
- UIKit的
ViewController默认被@MainActor标记,所以如果直接在ViewController的方法(比如viewDidLoad)里创建Task,这个Task会自动继承ViewController的MainActor上下文,代码默认在主线程执行,无需额外标注。 - 但你这段代码里的
Task是写在赋值给viewModel.dataChanged的闭包里的,这个闭包的执行时机和线程由ViewModel决定。如果ViewModel在后台线程调用dataChanged(),闭包执行时的上下文就是后台线程,此时创建的Task会继承这个后台上下文,不会自动切换到主线程。所以这种场景下必须显式添加@MainActor in来保证UI操作的正确性。
内容的提问来源于stack exchange,提问作者wolverine
相关产品推荐
相关产品推荐

