Setting font with layoutManager.setGlyphs

I have setup a NSLayoutManagerDelegate to display emojis for ASCII text on iOS, iPadOS, and Mac Catalyst.

For the first character (e.g., ":"), I set the emoji glyph (e.g., "😀"). For the remainder (e.g., ")"), I use a .null property so it doesn't display.

This almost works, but it's using the default font instead of "Apple Color Emoji", so it appears as a text symbol.

Here is the delegate code. Note that I have verified that the font used for the emoji glyph is the emoji font.

Code Block
func layoutManager(_ layoutManager: NSLayoutManager, shouldGenerateGlyphs glyphs: UnsafePointer<CGGlyph>, properties: UnsafePointer<NSLayoutManager.GlyphProperty>, characterIndexes indexes: UnsafePointer<Int>, font: UIFont, forGlyphRange range: NSRange) -> Int {
let count = range.length
var glyphs = Array(UnsafeBufferPointer(start: glyphs, count: count))
var properties = Array(UnsafeBufferPointer(start: properties, count: count))
var indexes = Array(UnsafeBufferPointer(start: indexes, count: count))
var fonts = Array(repeating: font, count: count)
if let textStorage = layoutManager.textStorage {
for i in 0..<count {
let range = NSRange(location: range.location + i, length: 1)
textStorage.enumerateAttribute(Composition.Key.emojiText, in: range, options: .longestEffectiveRangeNotRequired) {(value, range, stop) in
if let fragment = value as? Composition.Fragment {
if range.location == fragment.range?.location {
let string = NSAttributedString(string: fragment.text2, attributes: textStorage.attributes(at: range.location, effectiveRange: nil))
let line = CTLineCreateWithAttributedString(string)
let runs = CTLineGetGlyphRuns(line) as! [CTRun]
if let run = runs.first {
if let attributes = CTRunGetAttributes(run) as NSDictionary? {
let font = attributes[kCTFontAttributeName as String] as! UIFont
if CTRunGetGlyphCount(run) == 1 {
var glyph = CGGlyph()
CTRunGetGlyphs(run, CFRange(location: 0, length: 1), &glyph)
glyphs[i] = glyph
properties[i] = []
fonts[i] = font
}
}
}
} else {
glyphs[i] = CGGlyph()
properties[i] = .null
}
}
}
}
}
for i in 0..<count {
let range = NSRange(location: range.location + i, length: 1)
layoutManager.setGlyphs(&glyphs[i], properties: &properties[i], characterIndexes: &indexes[i], font: fonts[i], forGlyphRange: range)
}
return count
}


Is there something else I should do to set the font?
I've come to the conclusion that font support in NSLayoutManager.setGlyphs is broken for iOS/iPadOS/Catalyst. Only fonts stored in NSTextStorage will be used.

I changed my implementation to set the property to .controlCharacter with a .whitespace action. I then return the correct bounding box to hold the emoji font. Finally, I use a custom NSLayoutManager to do the rendering.

The last part is a pain when using a storyboard, since NSTextContainer.replaceLayoutManager doesn't work right either. But I figured out a workaround to that as well.
Setting font with layoutManager.setGlyphs
 
 
Q