4

I have a framework that supports CocaPods. I have now added support for Swift Package Manager but experiencing a crash when trying to access the framework's bundle.

    static func debuggerBundle(from target: AnyClass) -> Bundle {
        let podBundle = Bundle(for:  target)
        guard let bundleURL = podBundle.url(forResource: "Harlow", withExtension: "bundle"),
        let bundle = Bundle(url: bundleURL) else { fatalError("Must have a local bundle") }
        return bundle
    }

When installing with CocoaPods, the .ipa contains a /Frameworks folder with all the frameworks. But when running with SPM, the frameworks do not exist.

Using CocoaPods

Using CocoaPods

Using SPM

Using SPM

How do we access the framework's bundle with SPM?

https://github.com/stanwood/Harlow/

Tal Zion
  • 6,308
  • 3
  • 50
  • 73
  • See [this](https://betterprogramming.pub/how-to-add-resources-in-swift-package-manager-c437d44ec593). You should declare what resources to `.copy` in your package.swift, and then a `Bundle.module` will be generated for you. – Sweeper Apr 05 '21 at 10:47
  • @Sweeper what about `swift-tools-version 5.1` ? Looks like the Resources are supported from 5.3 only – Tal Zion Apr 05 '21 at 12:17
  • Yes that's right. I don't know what you should do for 5.1, except that you should probably update soon :) – Sweeper Apr 05 '21 at 12:18

1 Answers1

10

As mentioned in the comments, SPM package version 5.3 is the minimum for supporting bundle resources. If you need to maintain support for 5.1, you can add a second package file that includes support for 5.3: Package@swift-5.3.swift.

Using your Harlow repo as a base, the new Package file will look like this:

// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription

let package = Package(
    name: "Harlow",
    platforms: [
        .iOS(.v10)
    ],
    products: [
        // Products define the executables and libraries a package produces, and make them visible to other packages.
        .library(
            name: "Harlow",
            targets: ["Harlow"]),
    ],
    dependencies: [
        // Dependencies declare other packages that this package depends on.
        .package(url: "https://github.com/shu223/Pulsator.git", .upToNextMajor(from: "0.6.3")),
        .package(url: "https://github.com/schmidyy/Loaf.git", .upToNextMajor(from: "0.7.0")),
        .package(url: "https://github.com/stanwood/SourceModel_iOS.git", .upToNextMajor(from: "1.3.3"))
    ],
    targets: [
        .target(
            name: "Harlow",
            dependencies: ["Pulsator", "SourceModel", "Loaf"],
            resources: [.copy("Resources")]
        ),
        .testTarget(
            name: "HarlowTests",
            dependencies: ["Harlow"]),
    ],
    swiftLanguageVersions: [.v5]
)

This will make the Bundle.module reference become available. You could provide a static reference to this instance available through your Bundle extension like this:

extension Bundle {
    public static var harlow: Bundle = .module
}

With that in place, you should be able to use the harlow bundle reference to load your DefaultSettings.plist. (Bundle.harlow.url(forResource:withExtension:))

richardpiazza
  • 1,487
  • 10
  • 23