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

SwiftUI解码远程API返回JSON无报错但出现白屏问题求助

问题定位与修复方案

1. 解析环节问题排查

你打印的解码结果显示status、userProducts均为nil,属于解码失败,优先排查以下问题:

  • 先打印接口原始返回数据,确认实际返回结构和你预期的JSON一致,大概率是接口实际返回多了外层嵌套、或者字段名拼写/大小写不匹配:
    // 加在解码前
    if let jsonStr = String(data: data, encoding: .utf8) {
        print("接口原始返回: \(jsonStr)")
    }
    
  • 你所有模型字段都声明为可选类型,字段不匹配只会赋值为nil不会抛出解码错误,临时把UserProducts里的status: Bool?、userProducts: [UserProduct]?改成非可选类型,就能在catch块打印具体的解码错误位置。
  • 确认你填写的接口地址是有效的,你当前代码里接口地址填的是"...",无效地址会直接走url校验失败的分支,不会发起请求。

2. 界面层错误修复

  • onAppear位置错误:你现在把onAppear挂在ForEach后面,初始状态userProducts为空,ForEach不会渲染,loadShelf方法根本不会执行,把onAppear移到ScrollView的外层。
  • 强制解包风险:results.userProducts!如果为nil会直接触发崩溃,改用可选绑定处理空状态:
    if let products = results.userProducts, !products.isEmpty {
        ForEach(products) { product in
            VStack {
                Text("\(product.id ?? 0)")
            }
        }
    } else {
        Text("暂无商品数据")
    }
    
  • 类型不匹配错误:你原来的Text逻辑里,id是Int类型,你给的默认值是字符串"NA",类型不匹配就算有数据也无法显示,直接转成字符串输出即可。
  • 语法错误:body代码里多写了一个闭括号,把}).background里的多余右括号删掉。
  • 补充Identifiable协议:给UserProduct结构体加上Identifiable协议,即可直接遍历数组,不需要用下标:
    struct UserProduct: Codable, Identifiable {
        // 原有属性不变
    }
    

修复后的核心代码示例

struct ContentView: View {
    @State var results: UserProducts?

    var body: some View {
        VStack {
            ScrollView(.horizontal, showsIndicators: false) {
                HStack(spacing: 10) {
                    if let products = results?.userProducts, !products.isEmpty {
                        ForEach(products) { product in
                            VStack {
                                Text("\(product.id ?? 0)")
                            }
                        }
                    } else {
                        Text("加载中/暂无数据")
                    }
                }         
            }
            .background(Color(red: 250 / 255, green: 248 / 255, blue: 244 / 255))
            .onAppear(perform: loadShelf)
            Spacer()
        }
    }

    func loadShelf(){
        // 替换成你的真实接口地址
        guard let apiBaseURL = URL(string: "你的真实接口地址") else {
            print("Base URL is invalid.")
            return
        }
        let request = URLRequest(url: apiBaseURL)
        URLSession.shared.dataTask(with: request) { data, response, error in
            DispatchQueue.main.async {
                if let data = data {
                    // 新增原始数据打印排查
                    if let jsonStr = String(data: data, encoding: .utf8) {
                        print("接口原始返回: \(jsonStr)")
                    }
                    do{
                        let decoded = try JSONDecoder().decode(UserProducts.self, from: data)
                        self.results = decoded
                        print("decoded: \(decoded)")
                    }
                    catch{
                        print("Fetching data failed: \(error)")
                    }
                }
            }
        }.resume()
    }
}

内容的提问来源于stack exchange,提问作者Thorvald

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 16:45:00