Using playgrounds in local swift packages -- Bundle.module throws fatal error

Hello,

We are modularizing our iOS project using SPM. One of those modules is our UI module, which contains a bunch of Resources, for example, custom fonts.
In order to register the fonts, we use the following code to access the resources:
Code Block swift
Bundle.module.urls(forResourcesWithExtension: "otf", subdirectory: nil)


This is the recommended way from Apple as seen here.

This seems to be working when importing the module into our main app.

The problem appears when this code is executed from a Playground within the same module. When the code is executed, a fatal error is thrown:
Code Block
unable to find bundle named UniverseUI_UniverseUI


This is triggered from the generated file resource_bundle_accessor.swift which contains the following code:

Code Block swift
import class Foundation.Bundle
private class BundleFinder {}
extension Foundation.Bundle {
    /// Returns the resource bundle associated with the current Swift module.
    static var module: Bundle = {
        let bundleName = "UniverseUI_UniverseUI"
        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,
        ]
        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 UniverseUI_UniverseUI")
    }()
}


Lastly, our module target defines resources like so:
Code Block swift
resources: [.process("Resources")]),


Is there any workaround so we don't trigger the fatalError when executing that code from a playground? Any check to know if Bundle.module is available?

Thank you
This seems to work for me. I created a workspace and added a package and a playground to that workspace. I then added a resource to the package, and I was able to access that from the playground.

I’ve included a lot more details below.

I recommend that you retry this with a newly created workspace, package and playground, to confirm that the basics are working.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I’m using Xcode 12.4 on macOS 11.2.3.

Here’s my Package.swift:

Code Block
// 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: "MyLibrary",
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "MyLibrary",
targets: ["MyLibrary"]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "MyLibrary",
dependencies: [],
resources: [.process("Resources")]),
.testTarget(
name: "MyLibraryTests",
dependencies: ["MyLibrary"]),
]
)


As you can see, it’s a default file with your resources parameter added to it.

Here’s my package structure:

Code Block
% find MyLibrary
MyLibrary
MyLibrary/Tests
MyLibrary/README.md
MyLibrary/Package.swift
MyLibrary/Sources
MyLibrary/Sources/MyLibrary
MyLibrary/Sources/MyLibrary/MyLibrary.swift
MyLibrary/Sources/MyLibrary/Resources
MyLibrary/Sources/MyLibrary/Resources/Greeting.txt


Again, the only relevant change is the addition of my resource file.

Here’s MyLibrary.swift:

Code Block
import Foundation
public func testMyLibrary() {
let u = Bundle.module.url(forResource: "Greeting", withExtension: "txt")!
let greeting = try! String(contentsOf: u, encoding: .utf8)
print("\(Date()) \(greeting)")
}


Here’s my playground:

Code Block
import MyLibrary
testMyLibrary()


Running this produces:

Code Block
2021-04-22 09:58:52 +0000 Hello Cruel World!


where Hello Cruel World! is the contents of Greetings.txt.

Hi Eskimo, this seems not to be working anymore in Xcode 13.3, can you please check it out? I followed your steps exactly and I get Fatal error: unable to find bundle named .... Thanks.

I have created playground with swift package using that steps long time ago. After some time I opened that workspace on other machine and want to add local package dependency with same steps. it doesn't work.

But, By creating fresh new workspace and repeating steps I managed to get both local and remote packages work again with the same code base. I don't understand how xCode works at all =)

Using playgrounds in local swift packages -- Bundle.module throws fatal error
 
 
Q