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

Swift中Codable与Model Array结合:Alamofire JSON解析问题

没问题,这其实是Codable和网络请求结合的常见场景,我来给你一步步讲清楚怎么把接口响应解码到你的shipments数组里。

首先,你的模型结构是完全正确的——PagedShipments已经准确映射了接口的根节点(SearchResults对应结构体里的searchResults属性),这为解码打下了好基础。接下来结合Alamofire实现解码有两种常用方式,我都给你列出来:

方式一:用Alamofire内置的responseDecodable(最简洁)

Alamofire已经封装了Codable的解码逻辑,直接指定要解码的模型类型即可:

import Alamofire
import UIKit

class YourViewController: UIViewController {
    var shipments = [ShipmentModel]()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        fetchShipments()
    }
    
    private func fetchShipments() {
        let apiURL = "替换成你的实际接口地址"
        
        AF.request(apiURL)
            .validate() // 自动验证HTTP状态码是否在200-299范围内
            .responseDecodable(of: PagedShipments.self) { [weak self] response in
                guard let self = self else { return }
                
                switch response.result {
                case .success(let pagedData):
                    // 直接把解码后的数组赋值给你的全局变量
                    self.shipments = pagedData.searchResults
                    // 注意:UI更新要切换到主线程
                    DispatchQueue.main.async {
                        // 比如刷新你的表格视图
                        // self.tableView.reloadData()
                        print("成功加载\(self.shipments.count)条运单数据")
                    }
                case .failure(let error):
                    print("请求或解码失败:\(error.localizedDescription)")
                    // 这里可以给用户显示错误提示,比如弹框
                }
            }
    }
}

方式二:手动处理数据+JSONDecoder(更灵活)

如果你需要对原始数据做额外处理(比如日志打印、加密解密),可以先拿到Data再手动解码:

private func fetchShipmentsManually() {
    let apiURL = "替换成你的实际接口地址"
    
    AF.request(apiURL)
        .validate()
        .responseData { [weak self] response in
            guard let self = self else { return }
            
            switch response.result {
            case .success(let rawData):
                do {
                    let decoder = JSONDecoder()
                    // 要是接口日期格式特殊,这里可以配置解码策略,比如:
                    // decoder.dateDecodingStrategy = .iso8601
                    let pagedData = try decoder.decode(PagedShipments.self, from: rawData)
                    self.shipments = pagedData.searchResults
                    
                    DispatchQueue.main.async {
                        // self.tableView.reloadData()
                        print("手动解码成功,共\(self.shipments.count)条数据")
                    }
                } catch {
                    print("解码失败:\(error)")
                }
            case .failure(let error):
                print("网络请求失败:\(error.localizedDescription)")
            }
        }
}

几个关键注意点:

  • 避免循环引用:闭包里用[weak self],然后在闭包开头guard let self = self else { return },防止ViewController被内存泄漏。
  • UI更新必须在主线程:Alamofire的回调默认在后台线程,所以刷新UI一定要用DispatchQueue.main.async包裹。
  • 模型字段匹配:确保你的ShipmentModelDetails等子模型里的可选类型(比如customerNumber: Bool?)和接口返回的字段类型完全匹配,如果接口返回的是字符串而不是布尔值,会直接解码失败,这时候要调整模型或者添加自定义解码逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:59:38