Search code examples
iosswiftxcodestatic-librariesswift-package-manager

Xcode binary Swift Package static framework can't find resources at runtime


I'm working on deploying some existing swift packages as binary swift packages. They have to be static frameworks (company rules). One of them has a JSON resource that it uses as a config store, and ever since I converted it from a source-based swift package to be a static framework, it has been unable to find the resources that are supposed to be copied to it's bundle, causing runtime crashes.

The line that fetches the resource URL from the module bundle crashes at runtime.

let url = Bundle.module.url(forResource: "sample", withExtension: "json")!

Fails with the error:

2022-08-23 17:09:54.872641-0600 StaticLibConsumerAppDemo[44944:2189617] StaticLib/StaticLibDemo.swift:6: Fatal error: Unexpectedly found nil while unwrapping an Optional value

We have to redefine Bundle.module because Bundle.module is a Swift Package thing. When we compile to xcframework, we go through Xcode/xcodebuild instead, meaning Bundle.module can't be found at compile time. So we redefine it like this to keep from needing to change a bunch of code that was previously a valid (source-based) Swift Package. (This approach was used successfully in other packages. Just not this one...)

import Foundation

// MARK: - BundleFinder
private class BundleFinder {}

extension Bundle {
  static var module = Bundle(for: BundleFinder.self)
}

The sample.json file is successfully compiled into the xcframework (you can see it if you dig through the files), and non-resource parts of the binary swift package are useable without issue. The only problem arises when code from the static binary is trying to fetch resources from the bundle. This leaves me to think that either the resources aren't being included correctly in the bundle, or that the bundle being found at runtime isn't the static framework bundle that I expect to be found. I've poked around in the debugger a bit, but haven't been able to figure it out.

Full min example project(s) here:

App demo (where error arises): https://github.com/niehusstaab/StaticLibConsumerAppDemo

Binary package source: https://github.com/niehusstaab/StaticLibDemo

Anybody know where I'm going wrong?


Solution

  • Static libraries don't have bundles and so can't include resources. (Instead, their code is part of the main bundle.)

    You can create a separate resources bundle, and link the app to both the static library and the resources bundle.

    There's a nice article with detailed explanation here: https://medium.com/onfido-tech/reusing-code-and-resources-with-swift-static-libraries-and-resource-bundles-d070e82d3b3d .