SwiftUI调用API获取的字符串无法在View视图正常显示
问题根因
UI不更新的核心问题是调用方法的实例和UI绑定的实例不是同一个:
- 你在
ContentView中通过@StateObject var model3 = Api()创建了一个由SwiftUI托管生命周期的Api实例,Text组件的内容绑定的是这个实例的title属性,只有这个实例的@Published属性变更才会触发UI刷新。 - 但你在
.onAppear回调中写的是Api().getDataModelApi(),这行代码会生成一个全新的、用完即弃的临时Api实例,网络请求返回后修改的是这个临时实例的title和details,和UI绑定的model3没有任何关联,自然不会触发UI更新。你调试时看到title有值,实际是这个临时实例的属性被赋值,并非UI绑定实例的属性变化。 - 另外你现有代码中遍历返回数组循环给title、details赋值的写法,最终只会保留数组最后一个元素的内容,如果业务需要取指定位置的内容,不需要做全量循环。
修复方案
- 修正
.onAppear中的方法调用,不要新建Api实例,直接调用已经持有的model3实例的方法:
struct ContentView: View { @StateObject var model3 = Api() var body: some View { VStack { Text(model3.title) } .onAppear { // 直接调用当前View持有的被托管实例的方法 model3.getDataModelApi() } } }
- (可选优化)调整
getDataModelApi中的赋值逻辑,避免无意义的循环和重复主线程调度:
class Api : ObservableObject{ @Published var title : String = "" @Published var details : String = "" func getDataModelApi () { guard let url = URL(string: APIgetURL.demo) else { return } var request = URLRequest(url: url) let token = "38|xxxxx" request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization") URLSession.shared.dataTask(with: request) { data, response, err in guard let data = data, err == nil else { return } do { let dataModel = try JSONDecoder().decode([Model].self, from: data) // 按需取对应位置的数据即可,比如取第一条 guard let targetItem = dataModel.first else { return } DispatchQueue.main.async { self.title = targetItem.title self.details = targetItem.details } } catch { print("decode error: ", error) } } .resume() } // 原有getData方法无需改动 @Published var models : [Model] = [] func getData (url : String) { guard let url = URL(string: url) else { return } var request = URLRequest(url: url) let token = "38|xxx" request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization") URLSession.shared.dataTask(with: request) { data, response, err in guard let data = data, err == nil else { return } do { let dataModel = try JSONDecoder().decode([Model].self, from: data) DispatchQueue.main.async { self.models = dataModel } } catch { print("decode error: ", error) } } .resume() } }
注意:SwiftUI中
@StateObject、@ObservedObject订阅的是特定实例的属性变化,所有会影响UI的状态变更,必须作用在被View订阅的那个实例上,不要在视图逻辑中临时创建同类实例调用状态修改方法,否则必然出现状态和UI不同步的问题。
内容的提问来源于stack exchange,提问作者3sr0 store
相关产品推荐
相关产品推荐

