Type-safe resource accessors for Swift. Zero dependencies with a Bazel ruleset included.
- Xcode independent — Works with Bazel, SPM, or CLI
- No dependencies — During runtime or generation
- Bazel support —
swift_resources_libraryrule - Cross-platform — Accessors for UIKit, AppKit, and SwiftUI
Inspired by R.swift
Generated code uses Resources as the default namespace (change via --module-name).
Input: .ttf, .otf
// Fixed size
let font = Resources.fonts.lilexBold.font(size: 16) // SwiftUI
let uiFont = Resources.fonts.lilexBold.uiFont(size: 16) // UIKit
let nsFont = Resources.fonts.lilexBold.nsFont(size: 16) // AppKit
// Dynamic Type
let scaledFont = Resources.fonts.lilexBold.font(size: 16, relativeTo: .body)
let scaledUIFont = Resources.fonts.lilexBold.uiFont(size: 28, relativeTo: .title1)Input: .png, .jpg, .jpeg, .pdf, .svg, .heic, or imagesets from .xcassets
let image = Resources.images.logo.image // SwiftUI
let uiImage = Resources.images.logo.uiImage // UIKit
let nsImage = Resources.images.logo.nsImage // AppKitInput: colorsets from .xcassets
let color = Resources.colors.primary.color // SwiftUI
let uiColor = Resources.colors.primary.uiColor // UIKit
let nsColor = Resources.colors.primary.nsColor // AppKitInput: any file type (.json, .plist, .xml, .txt, etc.)
let url = Resources.files.config.url // URL?
let data = Resources.files.config.data // Data?Input: .xcstrings or .strings
let title = Resources.strings.localizable.welcomeTitle // Simple string
let msg = Resources.strings.localizable.greeting("World") // With argument
let items = Resources.strings.localizable.itemsCount(5) // Pluralized- Swift 5.9+
- macOS 13+ (for CLI font name extraction via CoreText)
- Bazel 7.x+ (for Bazel rules)
bazel_dep(name = "rules_swift_resources", version = "0.1.0").package(url: "https://github.com/jeffhodsdon/SwiftResources.git", from: "0.1.0")Swift:
swift build
.build/debug/sr generate --helpBazel:
bazel run //:sr -- generate --helpExample:
sr generate \
--fonts Resources/Fonts \
--images Resources/Images \
--xcassets Resources/Assets.xcassets \
--files Resources/Data \
--strings Resources/Localizable.xcstrings \
--output Generated/Resources.swift \
--module-name DesignSystem \
--access-level public| Flag | Default | Description |
|---|---|---|
--fonts <dir> |
— | Directories containing .ttf/.otf files (repeatable) |
--images <dir> |
— | Directories containing image files (repeatable) |
--xcassets <dir> |
— | Asset catalog directories (.xcassets) (repeatable) |
--files <dir> |
— | Directories containing data files (repeatable) |
--strings <path> |
— | String catalog (.xcstrings) or .strings files (repeatable) |
--development-region <lang> |
— | Source language for .strings files (auto-detected for .xcstrings) |
--output <path> |
stdout | Output Swift file path |
--module-name <name> |
Resources |
Generated enum namespace |
--access-level <level> |
internal |
public or internal |
--bundle <expr> |
BundleFinder | Bundle expression (.module, .main, or custom) |
--no-register-fonts |
— | Disable font registration code generation |
--force-unwrap |
— | Generate non-optional accessors with force unwrap |
load("@rules_swift_resources//rules_swift_resources:defs.bzl", "swift_resources_library")
swift_resources_library(
name = "DesignSystemResources",
fonts = glob(["Fonts/**/*.ttf"]),
images = glob(["Images/**/*.png"]),
xcassets = glob(["Assets.xcassets/**"]),
strings = ["Localizable.xcstrings"],
module_name = "DesignSystem",
)The macro creates a .resources filegroup for bundling:
swift_library(
name = "MyApp",
deps = [":DesignSystemResources"], # Type-safe accessors
)
ios_application(
name = "App",
deps = [":MyApp"],
resources = [":DesignSystemResources.resources"], # Bundle the files
)Note: swift_resources_library generates type-safe accessors but does not bundle resource files automatically. Use the .resources filegroup to include them in your app bundle.
Apache 2.0