Swift Package Manager - Integrating resources

Declaring resources

Resources can be bundled with a Swift package and then be accessed in your code.

We can distinguish two types of resources : common resources (e.g interface builder files, core data files, asset catalogs, lproj folders..) and custom resources (e.g .json files, .txt files, .md files..):

Adding the former is pretty straightforward as Xcode automatically treats them as resources. No changes need to be made to the package manifest.
Simply drag them under Sources/MyLibrary, consider using a subfolder for resources to distinguish them from source files.

Custom resources however must be explicitly declared in the package manifest.

targets: [
    .target(
        name: "MyLibrary",
        resources: [
            .process("Mocks")]
    ),
]

In above example, we explicity declare a “Mocks” resource that contains all our json files using the process(_:localization:) function.
The declared resources folder must reside in Sources/MyLibrary.

Accessing resources

If a target includes resources, Xcode creates a resource bundle and an internal static extension on Bundle to access it for each module.

The module static var becomes then accessible to access resources (module returns the resource bundle associated with the current Swift module)

To manage your mock files, you can then create Bundle method extension to load data from json…

extension Bundle {
    func dataFromResource(_ resource: String) -> Data {
        guard let mockURL = url(forResource: resource, withExtension: "json"),
                  let data = try? Data(contentsOf: mockURL) else {
                fatalError("Failed to load \(resource) from bundle.")
        }
      return data
    }
}

…and easily access them through the module.

Bundle.module.dataFromResource("mockName")

As mentioned by Apple, you should always use Bundle.module when you access resources. A package shouldn’t make assumptions about the exact location of a resource.

Provide public access if you want a resource be available to your apps.

public let someData = Bundle.module.dataFromResource(forResource: "mockFileName")

Apple’s documentation here.