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

本地Swift Package实例化Storyboard报找不到storyboard如何解决

问题描述

从本地Swift Package(以下简称SPM)中实例化ViewController时,始终收到Could not find a storyboard错误,当前实现代码如下:

let myViewController = UIStoryboard(
      name: "MyStoryboard",
      bundle: Bundle(
              url: Bundle.main.url(
                   forResource: "myModule_myModule",
                   withExtension: "bundle"
              )!
      )
).instantiateViewController(withIdentifier: "MyViewController")

上述代码在引用远程SPM依赖时可正常运行,但将SPM直接拖入Xcode作为本地依赖使用时就会触发报错。

根本原因

两种SPM引入方式的资源打包逻辑存在差异:

  • 远程引入的SPM依赖,资源会被打包为命名格式为[模块名]_[模块名].bundle的独立资源包,存放在主工程Bundle路径下,原有硬编码bundle名称的查找逻辑可以正常命中
  • 本地直接拖入的SPM依赖不会生成上述命名格式的独立资源bundle,资源直接挂载在对应模块的类关联的Bundle路径下,硬编码查找myModule_myModule.bundle会得到空值,最终导致Storyboard查找失败。
修复方法

放弃硬编码资源bundle名称的写法,使用SPM原生的Bundle定位逻辑,可同时兼容本地、远程两种引入场景:

  • 如果代码写在对应SPM模块内部,直接使用SPM自动生成的Bundle.module访问模块资源即可,写法最简洁:
let myViewController = UIStoryboard(
      name: "MyStoryboard",
      bundle: .module
).instantiateViewController(withIdentifier: "MyViewController")
  • 如果是在主工程或者其他模块跨模块调用该SPM的资源,先在目标SPM内声明一个公开的占位类,再通过Bundle(for:)方法定位对应模块的Bundle:
    1. 在目标SPM模块内新增公开类(无需额外实现逻辑,仅用于Bundle定位)
    public class ModuleBundleAnchor: NSObject {}
    
    1. 替换原有的Bundle初始化逻辑
    let myViewController = UIStoryboard(
          name: "MyStoryboard",
          bundle: Bundle(for: ModuleBundleAnchor.self)
    ).instantiateViewController(withIdentifier: "MyViewController")
    

注意:Bundle.module是SPM编译时自动生成的属性,仅能在对应模块的源码范围内访问,跨模块调用时无法直接使用,这类场景选择Bundle(for: 模块内类.self)的写法即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 14:36:30