You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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赋值的写法,最终只会保留数组最后一个元素的内容,如果业务需要取指定位置的内容,不需要做全量循环。
修复方案
  1. 修正.onAppear中的方法调用,不要新建Api实例,直接调用已经持有的model3实例的方法:
struct ContentView: View {
    @StateObject var model3 = Api()

    var body: some View {
        VStack {
            Text(model3.title)
        }
        .onAppear {
            // 直接调用当前View持有的被托管实例的方法
            model3.getDataModelApi()
        }
    }
}
  1. (可选优化)调整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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 10:42:21