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 ↗Chapters
Code shown on screen · 6 snippets
Enable support for NSAdaptiveImageGlyph in a UITextView
let textView = UITextView()
textView.supportsAdaptiveImageGlyph = true Read and write attributed string for serialization
// 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
// 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
// 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
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
// 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
Related sessions
-
21 min -
20 min