SwiftUI异步请求更新ViewModel报错:后台线程禁止发布变更
后台线程发布状态变更报错的修复方案
报错原因
async/await 机制下,URLSession.shared.data(for:) 会在后台线程完成网络请求和数据解析,后续的 countries = ... 赋值操作默认沿用这个后台线程。但SwiftUI要求所有@Published属性的更新必须在主线程执行,否则就会触发这个报错。
修复方法
方法1:手动切换主线程赋值
修改getCountries函数,把赋值操作放到主线程队列里:
func getCountries() async throws { let fetchedCountries = try await MainViewModel.countriesApi.fetchCountries() ?? [] DispatchQueue.main.async { self.countries = fetchedCountries } }
方法2:用MainActor强制主线程执行
可以直接给getCountries函数加上@MainActor修饰,让整个函数逻辑都在主线程跑:
@MainActor func getCountries() async throws { countries = try await MainViewModel.countriesApi.fetchCountries() ?? [] }
或者只在赋值时切换到MainActor:
func getCountries() async throws { let fetchedCountries = try await MainViewModel.countriesApi.fetchCountries() ?? [] await MainActor.run { countries = fetchedCountries } }
额外优化建议
你的fetchCountries方法里用try?会吞掉解码错误,建议换成try抛出错误,让上层统一处理:
func fetchCountries() async throws -> [Country]? { guard let url = URL(string: CountryUrl.countriesJSON.rawValue ) else { print("Invalid URL") return nil } let urlRequest = URLRequest(url: url) let (json, _) = try await URLSession.shared.data(for: urlRequest) let decodedResponse = try JSONDecoder().decode([Country].self, from: json) debugPrint("return decodeResponse") return decodedResponse }
内容的提问来源于stack exchange,提问作者agmcoder
相关产品推荐
相关产品推荐

