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

SwiftUI JSON解码器抛出空数据异常:iPhone XS调试问题求助

SwiftUI调试异常:iPhone XS反复出现JSON空数据解码失败,iPhone 8正常

问题情况

在XCode中学习SwiftUI时碰到特殊问题:两台iOS版本、开发配置完全一致的iPhone,调试时仅iPhone XS会出现JSON解码器抛出空数据的异常,临时修改代码重建项目能暂时解决,但次日问题必然复发;iPhone 8全程无此问题。

涉事代码

func loadJSON<T: Decodable>(_ filename: String) -> T {
    let data: Data

    guard let file = URL(string: filename)
        else {
            fatalError("Couldn't find \(filename).")
    }

    do {
        data = try Data(contentsOf: file)
    }
    catch {
        //fatalError("Couldn't load \(filename):\n\(error)")
        data = Data.init() // 如果删掉这行,异常会从上面的try行抛出
    }

    do {
        let decoder = JSONDecoder()
        return try decoder.decode(T.self, from: data)
    }
    catch {
        fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)") // <- 错误触发位置
    }
}

调试输出

Thread 2: Fatal error: Couldn't parse http://**myURL** as Array<ItemClass>:
dataCorrupted(Swift.DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840 "Unable to parse empty data." UserInfo={NSDebugDescription=Unable to parse empty data.})))

排查与解决建议

  • 替换同步网络请求:Data(contentsOf:)是同步网络请求,无超时控制、缓存管理,不同设备的网络栈处理逻辑存在差异,这是核心问题。换成URLSession异步请求,示例如下:
    func loadJSON<T: Decodable>(_ urlString: String, completion: @escaping (Result<T, Error>) -> Void) {
        guard let url = URL(string: urlString) else {
            completion(.failure(NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "无效URL"])))
            return
        }
        URLSession.shared.dataTask(with: url) { data, response, error in
            if let error = error {
                completion(.failure(error))
                return
            }
            guard let data = data else {
                completion(.failure(NSError(domain: "", code: -2, userInfo: [NSLocalizedDescriptionKey: "空数据"])))
                return
            }
            do {
                let decoded = try JSONDecoder().decode(T.self, from: data)
                completion(.success(decoded))
            } catch {
                completion(.failure(error))
            }
        }.resume()
    }
    
  • 移除空Data兜底逻辑:请求失败时直接返回错误,不要给空Data让解码器报错,便于定位真实问题
  • 清理项目缓存:删除XCode的Derived Data(路径:XCode→Preferences→Locations→Derived Data,点击右侧箭头打开文件夹删除),执行Clean后彻底重建项目
  • 重置设备网络:iPhone XS可能存在网络缓存异常,尝试重启设备或重置网络设置(设置→通用→传输或还原iPhone→重置→重置网络设置)
  • 检查URL合法性:确认传入的URL字符串无编码错误,若为本地文件,改用Bundle.main.url(forResource:withExtension:)构造本地文件URL

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 04:24:23