WWDC22 SALE: Save 50% on all my Swift books and bundles! >>

SOLVED: Widgets, SFSymbols and Custom User Icons

Forums > SwiftUI

Here's one that is currently racking my brain

It is for Widgets and concerns SFSymbols (icons) and custom user icons derived from SFSymbols. (Note that in an application this has not an issue in displaying icons in evaluated strings, as there are ways and means to do this.)

Imagine a dictionary that has entries that convert a key into an string that is either a SFSymbol or the name of custom user icon.

To display a SFSymbol you just use Image(systemName: ). However, you can also create an UIImage for the systemName, then convert the UIImage to an Image.

To display the custom user icon name you currently need to use UIImage(named: ), which you can convert to an image using Image(uiImage: )

Then have this function that will return an image corresponding to the name. This code example is purposefully kept simple, and not optimised.

func showSymbolImage(for imageName: String) -> Image {
    var outputImage: Image
    var uiImage: UIImage

    if imageName == "myCustomImage" {    // here imageName is the name of the custom image
        uiImage = UIImage(named: imageName)!    // force unwrap or nil-coalesce optional
        outputImage = Image(uiImage: uiImage)
    } else {
        uiImage = UIImage(systemName: imageName)!    // force unwrap or nil-coalesce optional
        outputImage = Image(uiImage: uiImage)
    }

    return outputImage
}

This I have not been able to make work in widgets, where I am passing an item's name translated through a dictionary in a ForEach loop.

If you comment out the 'else' part, then you see the custom icon. Correspondingly, if you comment out the 'if' part, then you see the SFSymbol. But it cannot process both.

So I have made a request to Apple, to provide the means to treat both SFSymbols and custom user symbols derived from, and conforming to, SFSymbols in the same way and interchangeably, especially since they introduced SFSymbols3 and interpolation.

In the meantime I am still racking my brain. Any thoughts?

   

The example code can be simplified to this, but it still only works as I described before.

func showSymbolImage(for imageName: String) -> Image {
    var outputImage: Image

    if imageName == "myCustomImage" {    // here imageName is the name of the custom image
        outputImage = Image(imageName)!    // custom icon / symbol - force unwrap or nil-coalesce optional
    } else {
        outputImage = Image(systemName: imageName)!    // sfsysmbol - force unwrap or nil-coalesce optional
    }

    return outputImage
}

Edit: or futher simplfied (and modified) to this

func showSymbol(for symbolName: String) -> Image {

    if symbolName == "myCustomSymbol" {    // here symbolName is the name of the custom symbol 
        return Image(symbolName ?? "exclamationmark.2")  // using nil-coalescing instead force-unwrap
    } else {
        return Image(systemName: symbolName ?? "exclamationmark.3")  // using nil-coalescing instead force-unwrap
    }
}

Note to self: Make sure that you include the custom symbols in the correct widget targets.

Still requesting Apple to look into improving this so that it is not necessary to write this type of translation function. Ideally, that would return the image irrespective of whether it is a SFSymbol or a custom symbol, or nothing if the name is not recognised.

    Image(symbol: imageName)

or at a push, wiht the usual 'nil / optional' caveats.

    Image(symbol: imageName ?? "")  // nil-coalescing
    Image(symbol: imageName!)       // force-unwrap

   

Updated the topic with the solution.

   

Save 50% in my Black Friday sale.

SAVE 50% To celebrate WWDC22, all our books and bundles are half price, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.

Save 50% on all our books and bundles!

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.