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

Swift中如何从Widget小组件包内的JSON文件读取数据?

报错原因

Bundle.main读取的是主App的资源包,Widget Extension是独立的扩展target,资源默认打包在专属的Widget bundle中,和主App资源包隔离,因此无法直接通过主包找到json文件。

解决步骤
  • 配置文件成员资格
    选中Xcode项目导航栏中的cars.json文件,打开右侧「文件检查器(File Inspector)」面板,在「Target Membership」区域勾选Widget Extension对应的target(如果主App也需要用到该文件,可以同时勾选主App target),保证文件会被打包进Widget的资源包。

  • 修改资源读取代码
    不要硬编码使用Bundle.main,改为明确传入Widget对应的bundle,同时拆分文件名和后缀减少匹配错误,优化后的代码示例如下:

// 通用解析方法增加bundle参数,默认兼容主App调用
func load<T: Decodable>(_ filename: String, suffix: String = "json", bundle: Bundle = .main) -> T {
    let data: Data

    guard let file = bundle.url(forResource: filename, withExtension: suffix)
    else {
        fatalError("Couldn't find \(filename).\(suffix) in \(bundle) bundle.")
    }

    do {
        data = try Data(contentsOf: file)
    } catch {
        fatalError("Couldn't load \(filename).\(suffix) from \(bundle) bundle:\n\(error)")
    }

    do {
        let decoder = JSONDecoder()
        return try decoder.decode(T.self, from: data)
    } catch {
        fatalError("Couldn't parse \(filename).\(suffix) as \(T.self):\n\(error)")
    }
}

// Widget中调用时传入Widget对应的bundle,替换为你自己的Widget Extension的Bundle ID
guard let widgetBundle = Bundle(identifier: "com.your.team.widget.bundle.id") else {
    fatalError("Can not find widget bundle")
}
var weeks: [CarTypes] = load("cars", bundle: widgetBundle)

Widget的Bundle ID可以在Xcode的TARGETS列表中选中Widget Extension,在「Signing & Capabilities」页面查看。

异常排查

如果配置后仍然报错,可以做如下校验:

  • 确认文件名大小写完全匹配,iOS文件系统大小写敏感,Cars.json和cars.json会被识别为不同文件
  • 编译成功后右键点击Xcode产物栏的.app文件,选择「显示包内容」,进入Plugins目录下的Widget扩展包,确认cars.json存在于资源目录中

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 11:36:05