I had a similar issue in my project as well. I have a Swift Package with Resources folder that contains fonts and asset catalogue,
Style/
- Source/
- Color.swift
- Resources/
- Processed/
- Colors.xcassets
- Fonts/
- MyFont.ttf
And this module is embedded in my Main.app. One of my unit test target CalendarTests.xctest
was accessing the apis of Style module. So when I ran the the CalendarTests.xctest
it was crashing here,
fatalError("unable to find bundle named Style_Style")
However when I run the Main app everything works fine, but only during the test run, I see this crash.
After digging through various build directories inside DerivedData, I noticed that my CalendarTests.xctest
contains a copy of Style_Style.bundle
, but the auto generated resource_bundle_accessor.swift
is not searching inside the "currently executing" test bundle, in this case CalendarTests.xctest/Style_Style.bundle
. The auto generated code looks for Bundle.main
and Style module's bundle(i.e PackageFrameworks/Style.framework/
), but not the bundle that is "currently executing".
In order to circumvent this problem, I made my own "bundle search" logic instead of relying on Bundle.module
property, which seems to fixed this crash.
This is my custom bundle search code,
extension Foundation.Bundle {
/// Returns the resource bundle associated with the current Swift module.
static var styleModule: Bundle = {
let bundleName = "Style_Style"
let candidates = [
// Bundle should be present here when the package is linked into an App.
Bundle.main.resourceURL,
// Bundle should be present here when the package is linked into a framework.
Bundle(for: BundleFinder.self).resourceURL,
// For command-line tools.
Bundle.main.bundleURL,
] + Bundle.allBundles.map { $0.bundleURL }
for candidate in candidates {
let bundlePath = candidate?.appendingPathComponent(bundleName + ".bundle")
if let bundle = bundlePath.flatMap(Bundle.init(url:)) {
return bundle
}
}
fatalError("unable to find bundle named Style_Style")
}()
}
The code looks identical to the auto generated code, except that I have additionally included Bundle.allBundles.map { $0.bundleURL }
to candidates
array.
All the classes in my Style module now uses the new Bundle.styleModule
property, instead of Bundle.module
.
The next thing Im gonna do is to create a macro as @SDGGiesbrecht suggested.
var candidates = [ ... ]
#if TESTING
candidates += Bundle.allBundles.map { $0.bundleURL }
#endif
...
Im not sure if this is a clean solution, but at least it gives a workaround solution while waiting for SR-13714.