Xcode 15.x static framework bundle access issues

Xcode 15 introduced official support for static frameworks.

This is presumably because there's quite a bit over overlap with the mergeable libraries feature.

Static frameworks potentially give developers a nice option for bundling resources with a static library. This was previously only really viable if you explicitly packaged up a .bundle with your .a (static library) which could be cumbersome for both the creator and consumer of a library. Or you explicitly copied your framework resources into your main app binary when building your app.

The release notes for Xcode 15 state:

Embedding a static framework using a Copy Files build phase now removes the static archive from the framework when it is embedded in the target bundle.

When inspecting the app target on disk this appears to be the case. In fact the behaviour is the same as with a mergable in release mode whereby a "stub" binary exists with no symbols.

The release notes also state:

The COPY_RESOURCES_FROM_STATIC_FRAMEWORKS build setting, previously used in the legacy build system to extract and copy the resources from a static framework to the target bundle, no longer has any effect with the new build system as the entire framework is copied instead

This also appears to be the case when inspecting the files on disk as the frameworks appear to be present in the main app with their resources.

So far so good. The issue arises when trying to access the bundle associated with this framework. The documentation doesn't mention any special access requirements to it's assumed that standard bundle access APIs should work.

Using a class

let bundle = Bundle(for: InfoCoreMain.self)

This returns the main application bundle and therefore fails to find the correct asset. This can be rationalised by the fact that the InfoCoreMain class does now actually exist within the main app target binary due to being statically linked. It's worth noting however, that mergable libraries in release mode do seem to work in this way and can resolve the bundle fine*.

Using an explicit bundle identifier

let bundle = Bundle(identifier: "***.***.InfoCore")

Using an explicit bundle identifier returns nil even though we can see the framework on disk.

Using a path

Using a path to access the framework also doesn't work.

if let bundlePath = Bundle.main.path(forResource: "InfoCore", ofType: "framework") {
    let bundle = Bundle(path: bundlePath)
    // Now you can access resources in the framework bundle
} else {
    // Framework bundle not found
}

All of the above is the same behaviour for release and debug builds. I have tried this on Xcode 15.2 and 15.3

*Mergeable libraries do seem to have issues in debug mode. See this forum post. https://forums.developer.apple.com/forums/thread/749818

I've modified a bit the using a path approach like

let bundleUrl = Bundle.main.privateFrameworksURL!.appendingPathComponent("StaticFramework.framework")
let bundle = Bundle(url: bundleUrl)

so that it works now.

It can be used as a workaround

Xcode 15.x static framework bundle access issues
 
 
Q