使用 SPM (Swift Package Manager) 获取本地文件的 URL

Bor*_* Y. 5 swift swift-package-manager

我试图.json在我的单元测试中读取文件并在 Swift 包中运行它。使用 Xcode 11 和 Swift 5.1

let path = Bundle.main.url(forResource: filename, withExtension: "json")
// Path is nil
Run Code Online (Sandbox Code Playgroud)

有人告诉我 Swift 包不再有捆绑包。那么我该如何解决这个问题呢?

我的 Swift.package 的一部分

.testTarget(
    name: "ProjectTests", 
    dependencies: [
        .target(name: "Project")
    ],
    path: "Tests",
    exclude: [
        "Folder/File.swift"
    ]
)
Run Code Online (Sandbox Code Playgroud)

Bor*_* Y. 5

我们找到的解决方案是FileManager

var cache: [String: URL] = [:] // Save all local files in this cache
let baseURL = urlForRestServicesTestsDir()

guard let enumerator = FileManager.default.enumerator(
    at: baseURL,
    includingPropertiesForKeys: [.nameKey],
    options: [.skipsHiddenFiles, .skipsPackageDescendants], 
    errorHandler: nil) else {
        fatalError("Could not enumerate \(baseURL)")
}

for case let url as URL in enumerator where url.isFileURL {
    cache[url.lastPathComponent] = url
}
Run Code Online (Sandbox Code Playgroud)

你将需要这个方法

static func urlForRestServicesTestsDir() -> URL {
    let currentFileURL = URL(fileURLWithPath: "\(#file)", isDirectory: false)
    return currentFileURL
        .deletingLastPathComponent()
        .deletingLastPathComponent()
}
Run Code Online (Sandbox Code Playgroud)

之后你可以获得每个文件的 URL:

func url(for fileName: String) -> URL? {
    return cache[fileName]
}
Run Code Online (Sandbox Code Playgroud)

如果您只想在 Swift 包中运行此代码,请使用#if SWIFT_PACKAGE.