The macro will then validate each case and the expanded macro will look something like this:
enum Symbols: String {
case circle
case circleFill = "circle.fill"
case shareIcon = "square.and.arrow.up"
case globe
var image: Image {
Image(systemName: self.rawValue)
}
var name: String {
self.rawValue
}
#if canImport(UIKit)
func uiImage(configuration: UIImage.Configuration? = nil) -> UIImage {
UIImage(systemName: self.rawValue, withConfiguration: configuration)!
}
#else
func nsImage(accessibilityDescription: String? = nil) -> NSImage {
return NSImage(systemSymbolName: self.rawValue, accessibilityDescription: accessibilityDescription)!
}
#endif
func callAsFunction() -> String {
return self.rawValue
}
}
In your code you can then call a symbol:
var body: some View {
VStack {
Symbols.circleFill.image
Label("Globe", systemImage: Symbols.globe.name)
// the above can also be written as
Label("Globe", systemImage: Symbols.globe())
}
}
In case the provided raw value is not a valid SF Symbol, Xcode will show a compile error at the enum-case in question:
Contribution
If you have any ideas on how to take this further I’m happy to discuss things in an issue.
SFSymbolsMacro
This Swift Macro provides an easy way to make the use of SF Symbols in Swift more or less “type-safe”.
Installation
Xcode
Swift Package Manager
In
Package.swift
:And then add the dependency to your targets.
Usage
Simply create an
enum
which will hold all the SF Symbols for your project:Then simply import
SFSymbolsMacro
and add the@SFSymbol
macro annotation to the enum:The macro will then validate each
case
and the expanded macro will look something like this:In your code you can then call a symbol:
In case the provided raw value is not a valid SF Symbol, Xcode will show a compile error at the
enum-case
in question:Contribution
If you have any ideas on how to take this further I’m happy to discuss things in an issue.