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
相关产品推荐
相关产品推荐

