为什么SwiftUI中解码JSON得到的数据无法赋值给State变量?
问题原因及修复方案
直接崩溃原因
addItem方法执行时,self.names是空数组,你生成随机下标用到的范围0..<self.names.count在数组长度为0时是无效区间,直接触发数组越界崩溃。
names无法赋值的核心原因
- 你在
ContentView的init方法中发起了异步网络请求,而@State修饰的属性在View初始化阶段还没有完成和视图生命周期的绑定,此时异步回调中对@State属性的赋值大概率不会生效,也无法触发视图更新。 - 你的代码错误吞掉了所有异常:网络请求失败的guard判断直接return,JSON解码的catch块为空,不管是网络出错、返回数据异常还是JSON结构不匹配导致解码失败,你都无法感知到问题,自然也不会走到赋值逻辑。
修复方案
- 把
getNames的调用从init移到onAppear修饰符中 - 给
addItem加数组非空判断,避免越界 - 补充错误日志输出,方便排查问题
- 避免强制解包、强制try的写法,减少崩溃风险
修复后参考代码
struct ContentView: View { @State var names:[String] = [] @Environment(\.managedObjectContext) private var viewContext var body: some View { List { // 展示CoreData的Person对象逻辑 } Button(action: addItem) .onAppear { getNames() } } func getNames(){ // URL & JSON 初始化逻辑 session.dataTask(with: request) { data, response, error in if let error = error { print("网络请求失败: \(error)") return } guard let data = data else { print("返回数据为空") return } do { let decoder = JSONDecoder() let decodedNames = try decoder.decode([String].self, from: data) DispatchQueue.main.async { self.names = decodedNames } } catch { print("JSON解码失败: \(error)") } }.resume() } func addItem() { guard !names.isEmpty else { print("名字列表还未加载完成") return } let p = Person(context: viewContext) p.age = String(Int.random(in: 1...100)) p.name = self.names[Int.random(in: 0..<self.names.count)] do { try viewContext.save() } catch { print("CoreData保存失败: \(error)") } } }
内容的提问来源于stack exchange,提问作者dooblr
相关产品推荐
相关产品推荐

