Gene McCulley
Gene McCulley

Reputation: 1267

Is it possible to use SF Symbols outside of UIImage?

I'm confused on how to use SF Symbols in text in an iOS project. I have a UIButton that uses a symbol just fine using UIImage systemImageNamed:. I would like to display a message about that button with some text in another view. I thought I should be able to use the Unicode reference to that symbol, but it doesn't render. My understanding is that these symbols are in the Private Use Area, but I cannot get them to render using code like @"Press the \U0010057C button."

I have tried importing the SFSymbolsFallback.ttf font file into my project.

I would expect to see the symbol rendered, but I get a ? instead.

Upvotes: 54

Views: 23583

Answers (4)

nayooti
nayooti

Reputation: 443

For iOS this snippet can safe you a little bit of time:

extension NSAttributedString {

    static func create(
        blocks: [Block],
        font: UIFont? = nil,
        textColor: UIColor? = nil,
        symbolColor: UIColor? = nil
    ) -> NSAttributedString {

        let font = font ?? .preferredFont(forTextStyle: .body)
        let textColor = textColor ?? .label
        let symbolColor = symbolColor ?? textColor

        let attributedBlocks: [NSAttributedString] = blocks.map { block in
            switch block {
            case .text(let text):
                return NSAttributedString(
                    string: text,
                    attributes: [
                        .font: font,
                        .foregroundColor: textColor
                    ]
                )
            case .symbol(let imageName):
                let attachment = NSTextAttachment()
                let imageConfiguration = UIImage.SymbolConfiguration(font: font)
                attachment.image = UIImage(
                    systemName: imageName,
                    withConfiguration: imageConfiguration
                )?.withTintColor(symbolColor)
                return NSAttributedString(attachment: attachment)
            }
        }
        let string = NSMutableAttributedString(string: "")
        attributedBlocks.forEach {
            string.append($0)
        }
        return string
    }
    
    enum Block {
        case text(String)
        case symbol(String)
    }
}

You might want to decorate your strings with \t,\n or separators of your choice.

Upvotes: 1

Noah Nuebling
Noah Nuebling

Reputation: 309

In macOS 13 Ventura you can simply copy-paste the symbols from the SF Symbols app into an NSString in Xcode, and it works great!

I also tested this under macOS 11 Big Sur. At first it didn't work, but then after I installed the SF Symbols app it started working.

So maybe this only works if the SF Symbols app is installed? I'm not sure.

Edit: It doesn't seem to be about the SF Symbols app but instead about the Fonts you have installed. You need to install certain fonts. SF Pro or something, in order for the SF Symbols to work in text.

Upvotes: 1

Michcio
Michcio

Reputation: 2876

This works for me:

let imageAttachment = NSTextAttachment()
imageAttachment.image = UIImage(systemName: "checkmark.circle")

// If you want to enable Color in the SF Symbols.
imageAttachment.image = UIImage(systemName: "checkmark.circle")?.withTintColor(.blue)

let fullString = NSMutableAttributedString(string: "Press the ")
fullString.append(NSAttributedString(attachment: imageAttachment))
fullString.append(NSAttributedString(string: " button"))
label.attributedText = fullString

Result:

enter image description here

Upvotes: 107

Werner Sharp
Werner Sharp

Reputation: 301

I have been struggling with this same problem of how to use SF Symbol glyphs using the CoreText rendering APIs. On MacOS, the "SF Pro Text" font has 7500+ glyphs in it including the SF Symbol glyphs. On iOS, the system font only has ~2800 glyphs and don't seem to include the new SF Symbol glyphs. Beyond including the font in the project itself (which is against Apple's licensing I believe), I have not found a way to render these glyphs using their Unicode character values.

Upvotes: 12

Related Questions