Building a Genmoji-Ready Input System in SwiftUI
Building a Genmoji-Ready Input System in SwiftUI
Exploring how to support Genmoji, rich text, and expressive input on iOS using SwiftUI + UIKit bridging.
Why This Matters
With the introduction of Genmoji in iOS 18, user expression is no longer limited to Unicode emoji. Instead, users can generate custom, image-based emoji directly from text prompts.
But here’s the catch:
Genmoji is not plain text — it’s a rich text glyph.
If your app only stores String, you’ll lose Genmoji data completely.
So the real challenge is:
- Supporting Genmoji input
- Preserving it through copy/paste
- Persisting it via serialization
- Restoring it without losing fidelity
This blog walks through building a minimal SwiftUI app that does exactly that.
Key Concept: Genmoji ≠ Emoji
Traditional emoji:
1 | |
Genmoji:
- Stored as image glyphs
- Embedded in
NSAttributedString - Backed by
NSAdaptiveImageGlyph
This means:
- You must use rich text
Stringis not enough
Architecture Overview
We’ll build a simple app with:
1 | |
Step 1: Bridging UITextView into SwiftUI
SwiftUI’s TextEditor does not support Genmoji.
We must use UITextView.
1 | |
Important Flags
| Property | Why it matters |
|---|---|
supportsAdaptiveImageGlyph |
Enables Genmoji input |
allowsEditingTextAttributes |
Enables copy/paste + rich editing |
Step 2: Persisting Rich Text (RTFD)
To preserve Genmoji, we must serialize the attributed string.
1 | |
Why RTFD?
Because it:
- Stores images + metadata
- Preserves Genmoji glyphs
- Is supported by UIKit
Step 3: Restoring Content
1 | |
Step 4: ViewModel
Keep logic out of views.
1 | |
Step 5: Preview UI
Display attributed text with another UITextView:
1 | |
Final Thoughts
Genmoji isn’t just a new feature — it represents a shift:
From text-based communication → to expressive, adaptive visual language
As iOS developers, this means:
- Thinking beyond strings
- Designing for rich content
- Treating text as a rendering system, not just data
- Store text as
NSAttributedString - Serialize with RTFD
- Restore via
NSAttributedString(data:)
If you’re building for modern iOS, this is no longer optional — it’s the future of user expression.