Xcode15 generated ImageResource with public access

Hi, for projects we used to use one SPM module for all application resources (Texts, Images, Fonts, ..) and use swiftgen to expose them safe and publicly for other modules.

I tried replacing swiftgen with the new resource catalog generation option in Xcode 15 and ran into not being able to make the generated structure public for other modules.

Is it possible to affect the generation with some parameter to add public access?

extension ImageResource {

    /// The "img_error_generic" asset catalog image resource.
    static let imgErrorGeneric = ImageResource(name: "img_error_generic", bundle: resourceBundle)

}

Thanks!

8 Likes

This is a great limitation and basically makes it unusable for us. Do you think we could write a Publify macro that goes through all the internal members of the ImageResource extension and exposes them as public with a certain prefix? The execution of the macro would have to happen after the asset symbol generation itself but I think this is the case. Something like

extension ImageResource {
    /// The "Share" asset catalog image resource.
    static let share = ImageResource(name: "Share", bundle: resourceBundle)

would be peered with

public extension ImageResource {
    /// The "Share" asset catalog image resource.
    static let iconShare = .share
1 Like

Yeah, just coming up against this now.

Was hoping I wouldn't have to resort to using SwiftGen but it looks like we'll have to use SwiftGen for now.

As far as I am aware this is not possible since the macro must be applied to the ImageResource struct itself and cannot be applied to e.g. a extension since otherwise it won't see the generated properties.

Also running into this issue.

My company has a separate swift package for our design system and reusable UI components. So all of our colors and images are also in this swift package.

Unfortunately because of this limitation, the Xcode asset catalog code gen is not useful for us.

Just a workaround, but to get around this I just expose resources via properties that I define. So if my UI library contains an image asset named "back_arrow", I'll expose it publicly by defining a static property on a UIImage extension using the resource initializer.

public extension UIImage {
    static let backArrowIcon = UIImage(resource: .backArrow)
}

This can be applied to ColorResource as well

This isn’t much of a workaround as you have to do it by hand. You are better off turning of Xcode code gen and using SwiftGen or writing a build plugin.

1 Like

So, as far I can read through the post:

  • Assets code completion only works for images and colors on Xcode 15
  • Work on either the main app or SPM modules, but they are not shareable (always internal)
  • No public access to asset resources
  • Only work for Swift (?) - no ObjC access

Can someone confirm this?

2 Likes