考虑一个带有
MyLibrary
和 MyExecutable
目标的简单 Swift 包。
目的是让 MyExecutable
使用 MyLibrary
(有图像)。
MyLibrary
目标有2个文件,一个Resources/Assets.xcassets
目录(其中有1个名为“Test”的图像)和一个Images.swift
文件,如下所示:
private extension NSImage {
static let test = Bundle.module.image(forResource: "Test")
}
public struct Images {
public static func printTestExists() {
print("Exists: \(NSImage.test != nil)")
}
}
请特别注意此处使用
Bundle.module
。 MyExecutable
仅包含一个 main.swift
文件,该文件导入 MyLibrary
并运行:
Images.printTestExists()
在 Xcode 中运行
MyExecutable
方案时,它按预期打印:
Exists: true
但是,当从命令行运行可执行文件时:
swift run -c release MyExecutable
它因错误而崩溃:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSBundle imageForResource:]: unrecognized selector sent to instance
为什么资产似乎无法从命令行运行?我只执行
swift run
命令,因此可执行文件应该可以访问库包,对吧?
资产按照您的预期作为资源进行处理
let package = Package(
name: "MyLibrary",
platforms: [.macOS(.v13)],
products: [
.library(name: "MyLibrary", targets: ["MyLibrary"]),
.executable(name: "MyExecutable", targets: ["MyExecutable"])
],
targets: [
.target(name: "MyLibrary", resources: [.process("Resources")] ),
.executableTarget(name: "MyExecutable", dependencies: ["MyLibrary"])
]
)
从命令行使用以下 SwiftUI 代码同样会不会显示图像,但在从 Xcode 运行时可以工作:
Image("Test", bundle: .module)
我在 Swift 论坛
上发现了类似的问题只回答我自己的问题,我相信问题只是swift run
不支持资产。希望未来的答案能够向我们展示如何使其发挥作用。
xcodebuild
命令解决了该问题
# Set this to what you want (this is inside the SPM .build directory)
derivedDataPath=".build/xcode-derived-data"
xcodebuild build \
-configuration release \
-scheme MyExecutable \
-sdk macosx \
-destination 'platform=macOS' \
-derivedDataPath "$derivedDataPath"
$derivedDataPath/Build/Products/release/MyExecutable
查看其他目的地运行
xcodebuild -showdestinations -scheme MyExecutable
它不需要
需要制作一个.xcodeproj
文件,这很好,所以我们可以留在SPM领域。尽管如此,
swift run
会更好,但我希望这能暂时有所帮助。