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

Swift使用Alamofire请求后DispatchQueue闭包未运行、视图无数据加载问题

问题排查与解决方案

根因定位

  • 核心问题出在JSON解析逻辑:你的Recipe、Ingredient结构体遵循Decodable协议时,默认会尝试解析所有存储属性,而你本地定义的id属性是自动生成的UUID,接口返回的JSON数据中没有对应id字段,导致解析直接失败。
  • 你使用try?进行解析操作,解析失败时会直接返回nil,所有错误信息被静默吞掉,无法定位问题,所以你看不到解析环节的报错,也走不到后续DispatchQueue的赋值逻辑。
  • 额外可能问题:你使用HTTP协议请求本地接口,iOS默认的应用传输安全(ATS)规则会拦截未配置信任的HTTP请求,也可能导致请求异常。

修复步骤

1. 给模型添加CodingKeys排除id字段

在两个模型中显式指定需要解析的字段,排除本地生成的id:

struct Recipe: Decodable, Identifiable {
    var id = UUID()
    var name: String
    var image: String
    var spirit: String
    var ice: String
    var glass: String
    var yield: String
    var description: String
    var ingredients: [Ingredient]

    // 仅枚举JSON中存在的字段,id不需要参与解析
    enum CodingKeys: String, CodingKey {
        case name, image, spirit, ice, glass, yield, description, ingredients
    }
}

struct Ingredient: Decodable, Identifiable {
    var id = UUID()
    var bottle: String
    var amount: String

    enum CodingKeys: String, CodingKey {
        case bottle, amount
    }
}

2. 替换try?为do-catch捕获错误

修改请求逻辑,显式捕获解析错误方便调试:

AF.request("http://localhost:3000/recipes").responseData { response in
    guard let data = response.data else { 
        print("请求无返回数据")
        return 
    }
    do {
        let decodedRecipes = try JSONDecoder().decode([Recipe].self, from: data)
        DispatchQueue.main.async {
            self.recipes = decodedRecipes
            print("解析成功,共\(decodedRecipes.count)条数据")
        }
    } catch {
        // 这里会打印具体的解析错误,比如字段缺失、类型不匹配等
        print("解析失败错误:\(error.localizedDescription)")
        print("详细错误信息:\(error)")
    }
}

你也可以直接使用Alamofire自带的responseDecodable简化代码:

AF.request("http://localhost:3000/recipes").responseDecodable(of: [Recipe].self) { response in
    switch response.result {
    case .success(let recipes):
        DispatchQueue.main.async {
            self.recipes = recipes
        }
    case .failure(let error):
        print("请求或解析失败:\(error)")
    }
}

3. 配置HTTP请求权限(可选)

如果请求被ATS拦截,可以在项目的Info.plist中添加本地接口的HTTP信任配置:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>localhost</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
            <true/>
        </dict>
    </dict>
</dict>

通用调试建议

  • 涉及Decodable解析的场景不要使用try?,必须显式捕获错误,Swift的DecodingError会明确告知缺失字段、类型不匹配等具体问题,定位效率极高。
  • 遇到解析异常时可以先把返回的data转成String打印,确认返回的JSON结构和预期一致,排除服务端返回异常的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 21:45:03