I would like to ship my library using Apple's Swift Package Manager. However my lib includes a .bundle file with several strings translated in different languages. Using cocoapods, I can include it using spec.resource. But in SwiftPM, I cannot do it. Any solution?
The package manager does not yet have any definition for how resources will be bundled with targets. We are aware of the need for this, but don't yet have a concrete proposal for it. I filed https://bugs.swift.org/browse/SR-2866 to ensure we have a bug tracking this.
Due to framework bundles not being supported yet, the only way to provide bundle assets with an SPM target is through a Bundle. If you implement code in your framework to search for a particular bundle in your main project (supporting asset bundles), you can load resources from said bundle.
Example:
Access the bundled resources:
extension Bundle {
static func myResourceBundle() throws -> Bundle {
let bundles = Bundle.allBundles
let bundlePaths = bundles.compactMap { $0.resourceURL?.appendingPathComponent("MyAssetBundle", isDirectory: false).appendingPathExtension("bundle") }
guard let bundle = bundlePaths.compactMap({ Bundle(url: $0) }).first else {
throw NSError(domain: "com.myframework", code: 404, userInfo: [NSLocalizedDescriptionKey: "Missing resource bundle"])
}
return bundle
}
}
Utilize the Bundled resources:
let bundle = try! Bundle.myResourceBundle()
return UIColor(named: "myColor", in: bundle, compatibleWith: nil)!
You can apply the same logic for all resource files, including but not limited to storyboards, xibs, images, colors, data blobs, and files of various extensions (json, txt, etc).
Note: Sometimes this makes sense, sometimes it doesn't. Determine use to own project's discretion. It would take very specific scenarios to justify separating Storyboards/Xibs into bundled assets.
You can also load individual resources dynamically.
Suppose your packages test need some mock JSON data. You'd place the mock JSON files in a Tests/JSONMocks
directory. Then in Package.swift
:
targets: [
.testTarget(
name: "MyTargetTests",
dependencies: ["MyTarget"],
path: "Tests"
),
]
And load them dynamically:
static func dataForJSONFileNamed(string: String) -> Data {
// find mock JSON files if using Swift Package Manager:
let currentDirectoryURL = URL(fileURLWithPath: FileManager.default.currentDirectoryPath)
let fileURL = currentDirectoryURL
.appendingPathComponent("Tests", isDirectory: true)
.appendingPathComponent("JSONMocks", isDirectory: true)
.appendingPathComponent(string)
.appendingPathExtension("json")
let jsonFileData = try! Data(contentsOf: fileURL)
return jsonFileData
}
来源:https://stackoverflow.com/questions/39815054/how-to-include-assets-resources-in-a-swift-package-manager-library