Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2024 SwiftUI & UI Frameworks

WWDC24 · 11 min · SwiftUI & UI Frameworks

Bring expression to your app with Genmoji

Discover how to bring Genmoji to life in your app. We’ll go over how to render, store, and communicate text that includes Genmoji. If your app features a custom text engine, we’ll also cover techniques for adding support for Genmoji.

Watch at developer.apple.com ↗

Transcript all transcripts

Chapters

Code shown on screen · 6 snippets

Enable support for NSAdaptiveImageGlyph in a UITextView swift · at 3:30 ↗
let textView = UITextView()
    textView.supportsAdaptiveImageGlyph = true
Read and write attributed string for serialization swift · at 4:41 ↗
// Extract contents of text view as an attributed string
let textContents = textView.textStorage

// Serialize as data for storage or transport
let rtfData = try textContents.data(from: NSRange(location: 0, length: textContents.length),
              documentAttributes: [.documentType: NSAttributedString.DocumentType.rtfd])


// Create attributed string from serialized data
let textFromData = try NSAttributedString(data: rtfData, documentAttributes: nil)

// Set on text view
textView.textStorage.setAttributedString(textFromData)
Decompose and recompose an attributed string swift · at 6:08 ↗
// Decompose an attributed string

func decomposeAttributedString(_ attrStr: NSAttributedString) -> (String, [(NSRange, String)], [String: Data]) {
    let string = attrStr.string
    var imageRanges: [(NSRange, String)] = []
    var imageData: [String: Data] = [:]
    attrStr.enumerateAttribute(.adaptiveImageGlyph, in: NSMakeRange(0, attrStr.length)) { (value, range, stop) in
        if let glyph = value as? NSAdaptiveImageGlyph {
            let id = glyph.contentIdentifier
            imageRanges.append((range, id))
            if imageData[id] == nil {
                imageData[id] = glyph.imageContent
            }
        }
    }
    return (string, imageRanges, imageData)
}
    
// Recompose an attributed string

func recomposeAttributedString(string: String, imageRanges: [(NSRange, String)], imageData: [String: Data]) -> NSAttributedString {
    let attrStr: NSMutableAttributedString = .init(string: string)
    var images: [String: NSAdaptiveImageGlyph] = [:]
    for (id, data) in imageData {
        images[id] = NSAdaptiveImageGlyph(imageContent: data)
    }
    for (range, id) in imageRanges {
        attrStr.addAttribute(.adaptiveImageGlyph, value: images[id]!, range: range)
    }
    return attrStr
}
Convert NSAttributedString to HTML swift · at 6:30 ↗
// Converting NSAttributedString to HTML

let htmlData = try textContent.data(from: NSRange(location: 0, length: textContent.length),
               documentAttributes: [.documentType: NSAttributedString.DocumentType.html])
Support Genmoji in communication notifications swift · at 7:33 ↗
func didReceive(_ request: UNNotificationRequest,
      withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {

  ...
  let message: NSAttributedString = _myAttributedMessageStringWithGlyph
  let context = UNNotificationAttributedMessageContext(sendMessageIntent: sendMessageIntent,
                                                       attributedContent: _message)    

  do {
    let messageContent = try request.content.updating(from: context)
    contentHandler(messageContent)
  } catch {
    // Handle error
  }
}
Render NSAdaptiveImageGlyph in custom typesetting solution swift · at 9:45 ↗
// Find typographic bounds for image in NSAdaptiveImageGlyph

let provider = adaptiveImageGlyph

let bounds = CTFontGetTypographicBoundsForAdaptiveImageProvider(font, provider)

// Draw it at the typographic origin point on the baseline

CTFontDrawImageFromAdaptiveImageProviderAtPoint(font, provider, point, context)

Resources