You need to enable JavaScript to run this app. Swift解析JSON数据时返回对象为nil 无法返回数组问题求助
优惠活动
大模型
产品
解决方案
定价
更多

Swift解析JSON数据时返回对象为nil 无法返回数组问题求助

问题根因
  • 核心问题为异步任务时序错误:URLSession.dataTask属于异步执行任务,调用resume()后网络请求会在后台线程运行,不会阻塞当前线程,函数会立刻执行return object语句,此时网络请求还未完成,回调闭包还没触发,object尚未被赋值,自然返回nil。你在void函数里能拿到正确数据,是因为打印逻辑写在了异步回调内部,会等请求完成后才执行。
  • 额外可优化点:Swift类型命名遵循大驼峰规范,你定义的struct catalogobject建议改名为CatalogObjectResponse,避免和内部的[CatalogObject]类型混淆,也能降低解码匹配失败的概率。
  • 不要对网络返回的data做强制解包,网络请求可能失败无返回数据,强制解包会导致App直接崩溃。
解决方案1:闭包回调(兼容所有Swift版本)

把同步返回改成异步回调,拿到结果后通过闭包传回调用方:

// 修正模型命名,遵循规范
struct CatalogObjectResponse: Hashable, Decodable, Encodable {
    let objects: [CatalogObject]?
}

// 函数改为无返回值,新增结果回调参数
func getCatalog(completion: @escaping ([CatalogObject]?, Error?) -> Void) {
     let url = URL(string: "https://connect.squareupsandbox.com/v2/catalog/list")!
     var request = URLRequest(url: url)
     request.httpMethod = "GET"
     request.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
     request.addValue("\(content_type)", forHTTPHeaderField: "Content-Type")
     request.addValue("\(square_version)", forHTTPHeaderField: "Square-Version")
    
    URLSession.shared.dataTask(with: request) { data, res, error in
        // 先处理错误,避免强制解包
        if let error = error {
            completion(nil, error)
            return
        }
        guard let data = data else {
            completion(nil, NSError(domain: "GetCatalog", code: -1, userInfo: [NSLocalizedDescriptionKey: "无返回数据"]))
            return
        }
        do {            
            let catalogdata =  try JSONDecoder().decode(CatalogObjectResponse.self, from: data)
            completion(catalogdata.objects, nil)
        } catch {
            completion(nil, error)
        }        
    }.resume()
}

// 调用示例
getCatalog { objects, error in
    if let error = error {
        print("请求失败: \(error)")
        return
    }
    guard let objects = objects else {
        print("无商品数据")
        return
    }
    // 拿到结果后如果要刷新UI需要切回主线程
    DispatchQueue.main.async {
        // 执行UI更新等后续操作
    }
}
解决方案2:async/await(Swift 5.5+ 推荐)

如果项目适配iOS 15+/macOS 12+及以上系统,可以用更简洁的新版Swift并发语法:

func getCatalog() async throws -> [CatalogObject]? {
     let url = URL(string: "https://connect.squareupsandbox.com/v2/catalog/list")!
     var request = URLRequest(url: url)
     request.httpMethod = "GET"
     request.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
     request.addValue("\(content_type)", forHTTPHeaderField: "Content-Type")
     request.addValue("\(square_version)", forHTTPHeaderField: "Square-Version")
    
    let (data, _) = try await URLSession.shared.data(for: request)
    let catalogdata = try JSONDecoder().decode(CatalogObjectResponse.self, from: data)
    return catalogdata.objects
}

// 调用示例
Task {
    do {
        let objects = try await getCatalog()
        DispatchQueue.main.async {
            // 执行后续操作
        }
    } catch {
        print("请求失败: \(error)")
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 07:45:04