我正在尝试在 Xcode (8 beta 2) 的命令行工具中获取资源的路径。这是我得到的:
在我的 main.swift 文件中,我有以下代码:
guard let filePath = Bundle.pathForResource("file",
ofType: "xyz",
inDirectory: "Resources") else{
fatalError("Could not find file")
}
每次都会触发
fatalError
。有什么想法吗?我知道命令行工具没有应用程序包,这就是为什么资源被复制到资源文件夹中,但我的 inDirectory
论点有点疯狂猜测......感谢您的阅读。
编辑:我的主要目标是从 CLT 访问资源文件(在本例中为文本文件)——我不喜欢这种特定的执行方式,所以如果有替代方法也很棒!
使用 Xcode 13.2 和 Swift 5,我遇到了同样的问题:我已将 JSON 文件拖到我的命令行工具项目中,但无法直接在我的代码中使用它。由于 CLT 似乎没有 Bundle,所以我找到了解决方法。
我创建了一个仅包含静态 let 属性的结构,其中包含我的 JSON 作为字符串:
struct CategoriesJSON {
static let string = """
... my JSON is here as plain text ...
"""
}
现在我只需拨打:
CategoriesJSON.string
即可使用它。
我知道这有点难看,但现在我的 JSON 已经在我的项目中了。
在最终二进制文件(命令行工具)中包含任意文件的一种方法是让链接器将它们包含在自定义 Mach-O 部分中,并从这些部分中获取它们。
设置起来有点不方便,但如果您的数据难以以字符串形式包含(例如图像或大型 XML 文件),则效果很好。
Resources/my.data
。Other Linker Flags
条目(在搜索字段中,您可以输入 OTHER_LDFLAGS
)。-sectcreate
__TEXT
$(SRCROOT)/Resources/my.data
这看起来像这样:
当您构建它时,链接器现在会将此文件包含到您的最终可执行文件中。如果文件丢失,您将收到链接器错误。
以下是如何在 Swift 中获取它:
import Foundation
/// Get resource embedded in the executable binary.
///
/// The resource needs to be embedded by the linker using the flag
/// `-sectcreate __TEXT [name] [path to file]`.
func getEmbeddedData(_ name: String) -> Data {
// All of this because `_mh_execute_header` is a `let` instead of a `var`,
// and `getsectiondata` does not accept copies of this value.
// See https://stackoverflow.com/a/49438718/400056
guard let handle = dlopen(nil, RTLD_LAZY) else {
fatalError("Cannot get handle to executable")
}
defer { dlclose(handle) }
guard let ptr = dlsym(handle, MH_EXECUTE_SYM) else {
fatalError("Cannot get symbol '\(MH_EXECUTE_SYM)")
}
let header = ptr.assumingMemoryBound(to: mach_header_64.self)
var size: UInt = 0
guard let rawData = getsectiondata(header, "__TEXT", name, &size) else {
fatalError("Cannot find resource '\(name)'")
}
return Data(bytes: rawData, count: Int(size))
}
作为解决方法,您可以使用源文件的绝对路径 例如,如果在 iCloud 驱动器上:
让路径=“/Users/myName/Library/Mobile Documents/com~apple~CloudDocs/myDirectory/file.xyz"