我正在尝试在我们的一个具有 Storyboard的项目中添加对 SPM 的支持。
目前我们获取它 UIStoryboard(name: String, bundle: String?)
但这似乎不适用于 SPM,因为实际上并没有 bundle 。即使打印所有 bundle 也不会显示我们包裹的 bundle 。
我们有什么方法可以支持 Storyboard,或者 SPM 仅仅是文件吗?
尝试:
UIStoryboard(name: "GiftCards", bundle: Bundle(for: self))
UIStoryboard(name: "GiftCards", bundle: Bundle(for: type(of: self)))
UIStoryboard(name: "GiftCards", bundle: Bundle(identifier: "com.x.x"))
最佳答案
更新:XCode 14.2(也许更早)不需要以下任何步骤。包中的 Storyboard会根据需要自动加载。感谢 @derpoliuk 的回答指出了这一点并提供了 GitHub 示例。
从 Xcode 12.0 开始,这种方法可以工作,但需要一些额外的步骤才能完成。
场景:
- 一个显示来自名为
BadgeKit
的包的嵌入式 Storyboard的应用 - 名为
BadgeKit
的 Swift 包,带有Package.swift
header//swift-tools-version:5.3
或更高版本 - BadgeKit 中名为
BadgeKit.storyboard
的 Storyboard
目标:
- 在应用 Storyboard中添加 Storyboard引用并使其在应用中运行
步骤:
将 Storyboard 引用添加到应用 Storyboard 并进行如下配置:
带有 Storyboard 值 BadgeKit
和 bundle 标识符 BadgeKit-BadgeKit-resources
的 Storyboard Reference 属性面板。
Xcode 自动生成一个包(及其标识符),以便您使用以下格式保存在 SPM 包中找到的资源:[包名称]-[包目标名称]-资源
。在我们的例子中,包名称和目标名称是相同的 (BadgeKit
)。
虽然 SPM 资源包始终在构建过程中创建并包含在应用程序中,但它们在运行时不会在包外部自动可用。如果您没有在代码中的任何位置导入和使用包的目标,Xcode 会尝试通过不加载该包的资源包来进行优化(这可能是 Apple 的一个疏忽,仅 Storyboard引用不足以触发此操作)。因此,如果您仅在 Storyboard 中使用 SPM 包的资源,则需要一种解决方法来诱骗 Xcode 使 SPM 包的 bundle 可用。
将此代码添加到应用的 AppDelegate.swift
文件中作为解决方法:
@UIApplicationMain final class AppDelegate: UIResponder {
[…]
override init() {
super.init()
// WORKAROUND: Storyboards do not trigger the loading of resource bundles in Swift Packages.
let bundleNames = ["BadgeKit_BadgeKit"]
bundleNames.forEach { (bundleName) in
guard
let bundleURL = Bundle.main.url(forResource: bundleName, withExtension: "bundle"),
let bundle = Bundle(url: bundleURL) else {
preconditionFailure()
}
bundle.load()
}
[…]
}
[…]
}
在我们的示例中,数组 bundleNames
包含一个字符串,该字符串对应于我们的包将在构建过程中为其资源创建的 bundle 的预期文件名。 Xcode 自动命名这些包文件,如下所示:[包名称]_[包目标名称].bundle
。请注意, bundle 的文件名与其标识符不同。
如果您想知道哪些包(及其相应的标识符)在运行时加载并可用,您可以使用以下代码进行故障排除:
let bundles = Bundle.allBundles
bundles.forEach { (bundle) in
print("Bundle identifier loaded: \(bundle.bundleIdentifier)") }
}
在SPM BadgeKit包中配置 Storyboard:
- 在“Module”中填写 SPM 包目标名称(“BadgeKit”)
- 取消选中“从目标继承模块”
关于storyboard - Swift 包管理器 - Storyboard包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58000140/