A Swift library that provides an SF Symbols-like API for third-party icon libraries. Use familiar SwiftUI patterns like Image(icon: "ph.house") to access Phosphor Icons and Ionicons with on-demand packaging via SPM Build Tool Plugin.
- Zero Configuration - Icons are bundled with the package; just add the dependency and start using icons
- SF Symbols-like API - Use
Image(icon: "ph.house")just likeImage(systemName: "house") - On-demand packaging - Only icons used in your code are bundled into your app
- SPM Build Tool Plugin - Automatic source scanning and asset generation at build time
- Template rendering - Full support for SwiftUI color modifiers like
.foregroundStyle() - Multiple icon libraries - Phosphor Icons (5 weights) and Ionicons (3 variants)
- All Apple platforms - iOS, macOS, watchOS, tvOS, and visionOS
- Swift 5.9+
- iOS 15+ / macOS 12+ / watchOS 8+ / tvOS 15+ / visionOS 1+
- Xcode 15+
Add SFSymbolsProvider to your Package.swift:
dependencies: [
.package(url: "https://github.com/CyonCode/SFSymbolsProvider.git", from: "1.0.0")
]Then add it to your target with the plugin:
.executableTarget(
name: "YourApp",
dependencies: ["SFSymbolsProvider"],
plugins: [
.plugin(name: "SFSymbolsProviderPlugin", package: "SFSymbolsProvider")
]
)Due to a limitation in how Xcode handles SPM build tool plugin outputs, iOS builds require a one-time setup:
- Add the package via File > Add Package Dependencies... and select SFSymbolsProvider library only
- In Build Settings, search for "User Script Sandboxing" and set it to No
- In your target's Build Phases, add a new Run Script Phase (after "Compile Sources")
- Add the following script:
"${BUILD_DIR}/../../SourcePackages/checkouts/SFSymbolsProvider/Scripts/ios-build-icons.sh"- Configure when the script runs (choose one):
- Option A: Uncheck "Based on dependency analysis" — script runs every build (recommended for development)
- Option B: Add Output File
$(DERIVED_FILE_DIR)/SFSymbolsProviderIcons.bundle— faster incremental builds, but requires Clean Build when icon usage changes
Note: macOS targets built with
swift buildwork without this extra step. The first build compiles the icon generation tool (adds ~5-10s).
import SwiftUI
import SFSymbolsProvider
struct ContentView: View {
var body: some View {
VStack {
// Phosphor Icons
Image(icon: "ph.house") // Regular weight
Image(icon: "ph.house.fill") // Fill weight
Image(icon: "ph.gear.bold") // Bold weight
// Ionicons
Image(icon: "ion.home") // Default variant
Image(icon: "ion.home.outline") // Outline variant
Image(icon: "ion.settings.sharp") // Sharp variant
}
}
}Icons use template rendering, so standard SwiftUI modifiers work seamlessly:
Image(icon: "ph.heart.fill")
.foregroundStyle(.red)
.font(.system(size: 24))
Image(icon: "ion.star")
.foregroundStyle(.yellow)
.frame(width: 32, height: 32)The initializer returns nil for invalid icon names, so use optional binding or provide a fallback:
// Optional binding
if let icon = Image(icon: "ph.house") {
icon
}
// With fallback
Image(icon: "ph.house") ?? Image(systemName: "house")public extension Image {
/// Creates an image from a Phosphor or Ionicons icon name.
/// - Parameters:
/// - iconName: The icon name in format "ph.name[.weight]" or "ion.name[.variant]"
/// - bundle: The bundle containing the generated assets (default: .main)
/// - Returns: An Image if the icon name is valid, nil otherwise
init?(icon iconName: String, bundle: Bundle = .main)
}| Provider | Format | Examples |
|---|---|---|
| Phosphor | ph.{name} |
ph.house, ph.gear, ph.user |
| Phosphor | ph.{name}.{weight} |
ph.house.fill, ph.gear.bold, ph.user.thin |
| Ionicons | ion.{name} |
ion.home, ion.settings, ion.person |
| Ionicons | ion.{name}.{variant} |
ion.home.outline, ion.settings.sharp |
| Weight | Description |
|---|---|
regular |
Default weight (no suffix needed) |
thin |
Thinnest stroke |
light |
Light stroke |
bold |
Bold stroke |
fill |
Filled/solid icons |
| Variant | Description |
|---|---|
default |
Default style (no suffix needed) |
outline |
Outline/stroke style |
sharp |
Sharp corners variant |
- Build Time Scanning: The SPM Build Tool Plugin scans your Swift source files for
Image(icon: "...")calls - Icon Detection: Regex-based detection identifies all Phosphor (
ph.*) and Ionicons (ion.*) references - Asset Generation: Only the icons you use are copied to a generated
.xcassetscatalog - Template Rendering: Icons are configured with
template-rendering-intentfor color customization
By default, SFSymbolsProvider uses bundled icons. To use custom icon paths (e.g., for newer icon versions), create a sfsymbols.json file in your package/project root:
{
"phosphorPath": "/path/to/phosphor-icons",
"ioniconsPath": "/path/to/ionicons.designerpack"
}- Xcode iOS builds require setup - SPM plugin outputs aren't automatically bundled for iOS. See Xcode Projects setup above.
- No Duotone support - Phosphor Duotone icons require special two-color rendering (planned for v2.0)
- String literals only - Dynamic icon names like
Image(icon: variable)are not detected at build time - SwiftUI only - No UIKit/AppKit API provided
- No Symbol Effects - iOS 17+ symbol animations are not supported
- Verify the Run Script Phase is after "Compile Sources" in Build Phases
- Ensure "Based on dependency analysis" is unchecked - the script must run every build
- Clean and rebuild - Product > Clean Build Folder (⇧⌘K), then rebuild
- Check the bundle exists - Look for
SFSymbolsProviderIcons.bundlein your app's .app folder
The first build compiles the icon generation tool from source. Subsequent builds reuse the cached tool and only take a few seconds.
The script uses env -i to isolate the Swift build from Xcode's environment. If you still have issues, ensure you have Swift command line tools installed: xcode-select --install
Check the Build Log (⌘8) for "com.apple.actool.compilation-results" which shows the path to the generated Assets.car file.
See the Example/ directory for a complete iOS app demonstrating all features:
cd Example
swift buildSFSymbolsProvider is available under the MIT license. See the LICENSE file for more info.
- Phosphor Icons - Beautiful open-source icons
- Ionicons - Premium icons for Ionic Framework
- phosphor-swift - Inspiration for the implementation approach