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

SwiftUI调用API时出现Thread 4 'try!'表达式致命错误如何解决?

问题根因

你遇到的两个问题均源于Post结构体的id字段定义与接口返回规则、Codable协议的解码逻辑不匹配:

  • 解码崩溃:你请求的接口返回的post数据中id为整数类型,而你定义的Post结构体id是UUID类型,JSONDecoder做类型转换时失败触发崩溃
  • let id编译报错:Codable默认会自动解码所有存储属性,用let声明的常量无法在解码时被重新赋值,因此编译器要求改为var

解决方案

你可以根据需求选择以下任意一种方案修复:

方案1:仅使用本地UUID作为唯一标识(不需要接口返回的id)

手动指定CodingKeys,将id字段排除在解码逻辑之外,修改Data.swift中的Post结构体代码:

struct Post: Codable, Identifiable {
    // 这里用let声明也不会编译报错
    let id = UUID()
    var title: String
    var body: String
    
    // 仅指定需要解码的字段,id不参与解码
    enum CodingKeys: String, CodingKey {
        case title, body
    }
}

方案2:使用接口返回的id作为唯一标识

直接修改id的类型和接口返回的整数类型对齐,不需要额外配置CodingKeys:

struct Post: Codable, Identifiable {
    // 和接口返回的Int类型id匹配
    var id: Int
    var title: String
    var body: String
}

额外优化建议

不要使用try!、data!这类强制解包语法,接口异常、网络失败时会直接触发崩溃,可以修改Api类的请求逻辑做兼容处理:

class Api{
    // 注意你之前的拼写错误:completition改为正确的completion
    func getPosts(completion: @escaping([Post]) -> ()){
        guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else { return }
        
        URLSession.shared.dataTask(with: url) { (data, _, error) in
            // 先判断数据是否正常返回
            guard let data = data, error == nil else {
                DispatchQueue.main.async {
                    completion([])
                }
                return
            }
            do {
                let posts = try JSONDecoder().decode([Post].self, from: data)
                DispatchQueue.main.async {
                    completion(posts)
                }
            } catch {
                print("解码失败: \(error.localizedDescription)")
                DispatchQueue.main.async {
                    completion([])
                }
            }
        }
        .resume()
    }
}

内容的提问来源于stack exchange,提问作者Manuel Orozco Jimenez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 06:39:03