First-party typed accessors for Asset Catalog resources via build-tool plugins

Accessing Asset Catalog resources (colors, images, strings, etc.) in Swift currently relies on string-based APIs such as UIColor(named:), which provide no compile-time safety, no autocomplete, and fail silently at runtime when assets are missing or renamed.

As a result, most production teams rely on third-party code generation tools (e.g. SwiftGen) to generate typed accessors for asset catalog entries. This pattern is extremely common but lives entirely outside the Swift toolchain.


Current ecosystem state

Today, teams typically choose between:

  • String literals (UIColor(named: "PrimaryBackground"))

  • Manually maintained enums or wrappers

  • Third-party generators (SwiftGen, R.swift, custom scripts)


Proposed direction

Provide an official, first-party mechanism—ideally via SwiftPM Build Tool Plugins—to generate typed Swift accessors for asset catalog resources at build time.

For example, a generated API shape like:

UIColor.Assets.primaryBackground
ImageAssets.logo
Strings.welcomeTitle
1 Like

Correct me if I’m wrong, but the compiler already generates ImageResource, ColorResource and LocalizedStringResources (where marked for generation in String Catalogs), which can be converted to these types with framework initializers.

This we already have, since Xcode 15 (for images and colours) and since Xcode 26 (for strings).

Settings:
Generate Asset Symbols
Generate Swift Asset Symbol Extensions
Generate Swift Asset Symbol Framework Support

Relevant WWDC 2023 fragment

Settings:
Generate String Catalogue Symbols

Relevant WWDC 2025 fragment

1 Like

A followup question though: can't see how to use this in packages, is it available there?

Yes, I’ve since realized that this does exist on the SwiftUI side, and Apple has provided bridging APIs so those generated resource types can also be used from UIKit (e.g. UIImage(resource:), UIColor(resource:)).

That said, it would be nicer if this were integrated directly and idiomatically into UIKit, for example with something like:

UIImage.Assets.myImage
UIColor.Assets.myColor

This would make the distinction explicit and provide a UIKit-native, discoverable way to access custom images and colors. While UIImage(resource: .myImage) does work, the current approach still feels SwiftUI-driven rather than UIKit-first.

Given that the vast majority of production codebases are still built with UIKit (especially larger, long-lived apps), having first-class, discoverable asset APIs would significantly improve the developer experience for teams that are either staying with UIKit or migrating gradually to SwiftUI.

Yes, It works in Swift Packages, but the project settings are per target. You’ll need to enable the “Generate String Catalog Symbols” build setting in your package’s .xcconfig or set it directly in the package manifest:

.target(
    name: "MyLibrary",
    swiftSettings: [
        .define("ASSET_SYMBOLS_ENABLED") // or via buildSettings dictionary if needed
    ]
)

If you’re using asset catalogs in a package, the image/color symbols should generate automatically with the Xcode 15+ settings enabled.

That said, the API you get (String(localized: .welcomeTitle), UIImage(resource: .logo)) still feels SwiftUI‑first. A UIKit‑native wrapper like UIImage.Assets.logo would make migration and mixed‑codebase work much smoother.

Have you tried "Generate Swift Asset Symbol Extensions: YES"? It gives you almost what you want:

UIImage.myImage // this form requires Generate Swift Asset Symbol Extensions: YES
UIImage(resource: .myImage) // this works without the above key

Ditto with the colours.

There is no equivalent of "Generate String Symbol Extensions" for strings AFAIK, but compared to a hypothetical String.myKey the String(localized: .myKey) form is "superior" in that it allows to easily search for all "String(localized:" instances across source files.


A followup question though: can't see how to use this in packages, is it available there?

I gave it another go – turns out it works out of the box for image/colour assets and strings.

The only thing that doesn't work is using the extension form of image/colours.

This works (from within my package):

String(localised: .myString) // if string is inside "Localizable.xcstrings"
String(localised: .OtherTable.otherString) // if string is inside "OtherTable.xcstrings"
UIImage(resource: .myImage) // regardless of the asset file name
UIColor(resource: .myColor) // regardless of the asset file name

This doesn't work (from within my package):

UIImage.myImage // requires "Generate Swift Asset Symbol Extensions: YES"
UIColor.myColor // requires "Generate Swift Asset Symbol Extensions: YES"

This doesn't work either (from normal app target either), although I guess this is expected:

UIImage.AssetFileName.myImage // does not ever compile (expectedly?)
UIColor.AssetFileName.myColor // does not ever compile (expectedly?)
UIImage(resource: .AssetFileName.myImage) // does not ever compile (expectedly?)
UIColor(resource: .AssetFileName.myColor) // does not ever compile (expectedly?)

Is that possible at all? I tried that but there's no "target" shown for my package, and setting xcconfig file on it's "project" level doesn't seem to do anything.

You mean this key specifically: "ASSET_SYMBOLS_ENABLED" ? I don't see it documented anywhere. For image/colour extension generation I tried setting:

.define("ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS")

but that doesn't work (besides it feels wrong to use it with .define(...), e.g. it doesn't allow setting the key to false, other than commenting it out).

"or via buildSettings" - what exactly is this? I do not see this parameter or ability to change build settings for my package via Xcode UI.

Relevant keys for xcconfig files (or Xcode settings in UI)

Images/colours:

ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES
ASSETCATALOG_COMPILER_GENERATE_ASSET_SYMBOLS = YES

strings:

STRING_CATALOG_GENERATE_SYMBOLS = YES

Thanks for the detailed follow up you've essentially reverse engineered the exact workflow I had in mind. It's great to confirm that UIImage.myImage works once Generate Swift Asset Symbol Extensions is enabled. That's almost what I was hoping for.

Honestly, I wasn't even aware this option existed and I suspect many UIKit developers aren't either. I've seen numerous projects still using manual enum wrappers or raw UIImage(named:) strings, which suggests this feature isn't discoverable enough in its current form.

The remaining friction especially how this setting isn't easily exposed or consistently configurable in Swift Packages highlights the kind of tooling gap that would benefit from official, first party support. Ideally, these generated symbols should be:

  1. Discoverable: available via autocomplete without needing to dig through build settings.

  2. Consistently configurable: whether in an app target, Swift package, or Xcode project.

  3. UIKit‑idiomatic: even with UIImage.myImage, the flat naming still feels like a generated artifact rather than a designed UIKit API.

What I'm advocating for is taking this existing but tucked‑away capability and making it a polished, intentional part of the UIKit development experience something like UIImage.Assets.myImage that feels native, grouped, and designed rather than generated.

Note that currently you won't be able having the same image/colour name in two assets, so this is currently no-go (if specifying asset name was possible to begin with I mean):

// pseudo-code ahead:
UIImage.FirstAssets.myImage
UIImage.OtherAssets.myImage

Until Xcode asset support is improved there's this hack, which brings you half-way to grouping (but without any safety or checking you grouped things right):

extension UIImage {
    typealias FirstAssets = UIImage
    typealias OtherAssets = UIImage
}
...
UIImage.FirstAssets.firstImage
UIImage.SecondAssets.secondImage
UIImage.FirstAssets.secondImage // no checking here

Personally I'd welcome the addition of some tooling support for icon / colour asset symbols being drawn inline in Xcode (like we had with image and colour literals (in fact I am still using those for the benefit of this WYSIWYG aspect (despite image literals not being type safe :sad_but_relieved_face:))).

Literals in text form (we already have this):

func theTest() {
    let image = #imageLiteral(resourceName: "myImage")
    let color = #colorLiteral(red: 1, green: 0, blue: 0, alpha: 1)
}

Literals in Xcode UI (we already have this):

Could be similar with assets, e.g.:

Assets in text form (we already have this):

func theTest() {
    let image = UIImage.myImage
    let color = UIColor.myColor
}

Assets in Xcode UI (wanted feature):


The improvements you are suggesting are useful quality of life improvements. The best place for them would be feedback assistant report (for "Developer Tools & Resources" / "Xcode").

1 Like

Thanks for the insights. The typealias hack is clever, and the collision issue really shows why current symbols feel like a workaround rather than a designed API.

Inline previews for asset symbols in Xcode would be a huge discoverability win. I'll file this in Feedback Assistant as you suggested. Even if full UIImage.Assets.myImage grouping isn't feasible yet, better previews and clearer package configuration would go a long way.

Appreciate the deep dive this has been super informative.

Since discoverability has been mentioned as a significant issue, I did want to highlight that namespacing (e.g. UIImage.Navigation.logo and UIImage.Homescreen.logo) can be achieved.

In the asset catalog you can group your images/colors by namespaced folders by either making one directly via the new menus or selecting existing folders and ensuring the “Provides Namespace” checkbox ticked in the Attributes Inspector. The generated symbol will then be namespaced as well.

2 Likes

Great! I confirm this already works if I set "Provides Namespace" to on on the "Folder".

    UIImage.Folder.someImage
    UIImage(resource: .Folder.someImage)

Interestingly the name clashing is also not an issue with namespaced folders, e.g. these could be three different images:

            Image(.Folder1.someImage)
            Image(.Folder2.someImage)
            Image(.someImage)

Great find, thank you for sharing this. It is exactly the API pattern I had in mind.

I did search for this approach but could not find any documentation or tutorials covering it. It seems this feature has not reached broader awareness yet. Even LLMs do not mention it, and most discussions still point to string literals or third party generators.

For a feature like this to truly benefit the community, it needs to be more discoverable. Right now, teams may keep using workarounds simply because they are not aware that built in namespacing exists.

Correct, those assets don’t clash and is the exact purpose Asset Catalogs have supported namespacing for a long time. It’s with noting that namespaces are nothing new as you could use them with the string APIs too e.g. UIImage(named: "Namespace/image")

While I’m sure there is probably some upper limit to how many namespaces can be nested, I’ve never reached one, so you could end up with something like UIImage(named: "Homescreen/AB/Modern/Icons/user") which in the new symbols would be UIImage.Homescreen.AB.Modern.Icons.user

1 Like

WWDC18 video fragment describing asset namespaces.

And indeed namespaces feature is even older than this as I could see mentions of them from 2015. TIL

This is still all internal though isn’t it ? Meaning you can’t really put all your shared resources in a single module that you share without manually exposing public getters

1 Like

Yes, all internal! I really wish we‘d have control over the generated access levels.

This brings us to a list of desirable features that are currently missing:

  1. full support in Swift packages (e.g. Generate Swift Asset Symbol Extensions on/off)
  2. WYSIWYG (like colorLiteral / imageLiteral)
  3. ability to mark the asset file itself namespaced, without explicitly creating a top level "folder" in it just for namespacing.
  4. customising Swift visibility levels
  5. similar symbol generation for font assets
1 Like