How to include assets / resources in a Swift Package Manager library?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Swift Package Manager can bundle resources such as images, JSON files, audio, and localized strings directly inside a package target. The normal setup is to declare those resources in Package.swift, place the files inside the target directory, and load them through Bundle.module. This capability requires Swift tools version 5.3 or later.
Add Resources to the Target Definition
Resources belong to a target, not to the package globally. A minimal manifest looks like this:
.process("Resources") tells SwiftPM to bundle the contents of that directory. If you need the files copied without processing, use .copy("Resources") instead.
Organize the Package Layout Clearly
A common directory structure is:
Keeping resources under one folder inside the target makes the manifest simple and reduces path mistakes. The important rule is that the resources must live under the target directory so SwiftPM can associate them with that target.
Load Files with Bundle.module
At runtime, load package resources from Bundle.module, not from Bundle.main:
This is the key runtime detail. The consuming app is not the owner of the package bundle, so Bundle.main is the wrong place to look.
Load Images from the Package Bundle
If the resource is an image, you can still use the package bundle directly. With UIKit, for example:
This keeps the lookup logic inside the package instead of forcing the app target to know how the package stores its resources.
Test Resource Access Explicitly
A package can compile while resource loading is still broken, so add a small test that actually opens a file:
That catches missing manifest entries, wrong filenames, and path mistakes much earlier.
Keep Resource Access Inside the Package
A good package API hides bundle lookup details from consumers. Instead of asking app code to locate package files manually, expose helper functions that return decoded data, images, or strings. That keeps the resource contract stable even if the internal package layout changes later.
Common Pitfalls
- Using
Bundle.maininstead ofBundle.module. Package resources are not stored in the main app bundle. - Forgetting to declare resources in
Package.swift. Files on disk are not bundled automatically. - Choosing
.copywhen you expected processing behavior, or.processwhen exact original layout mattered. - Placing resource files outside the target directory so SwiftPM does not associate them with the target.
- Assuming a successful build proves resource loading works. Add runtime tests that actually fetch the files.
Summary
- Declare package resources in the target definition inside
Package.swift. - Store the files under the target directory, usually in a
Resourcesfolder. - Load them with
Bundle.module. - Use
.processor.copybased on how the files should be bundled. - Add tests that open a real bundled resource so configuration mistakes are caught quickly.

