A modern, native rich text editor built with SwiftUI and iOS 26+ APIs. This demo showcases the power of AttributedString, AttributedTextSelection, and TextEditor to create a fully-featured text formatting experience without UIKit.
- Bold - Make your text stand out
- Italic - Add emphasis with style
- Underline - Highlight important content
- Strikethrough - Mark completed items or revisions
- Text Color - Full color picker for foreground text
- Background Color - Highlight text with custom backgrounds
- Clear Background - Remove highlighting with one tap
- Font Size Control - Adjust from 8pt to 72pt
- Increment/Decrement - Precise 2pt adjustments
- Visual Feedback - Live size indicator
- Active State Indicators - Visual feedback for applied formatting
- Clear Formatting - Remove all formatting with one tap
- Select All - Quick text selection
- Sample Text Insertion - Demo formatted text
- Character Counter - Track document length in real-time
- Horizontal Scrolling Toolbar - Fits all controls elegantly
- Color Picker Integration - Native iOS color selection
- Status Bar - Live document statistics
- Responsive Design - Works on all iOS devices
I have also written detaild article on this which explains it well, You can have a look here: https://medium.com/@dkvekariya/how-to-build-rich-text-editor-in-swiftui-f09a39d2dce9
| mac Editor dark |
|---|
|
- Xcode 16.0+ or later
- iOS 26.0+ deployment target
- macOS Sonoma or later (for development)
-
Clone the repository
git clone https://github.com/yourusername/swiftui-rich-text-editor.git cd swiftui-rich-text-editor -
Open in Xcode
open RichTextEditorDemo.xcodeproj
-
Build and Run
- Select your target device or simulator
- Press
β + Rto build and run
RichTextEditorDemo/
βββ ContentView.swift # Main editor view
βββ ToolbarButton.swift # Reusable toolbar button component
βββ RichTextEditorApp.swift # App entry point
βββ Assets.xcassets/ # App assets
The app leverages fontResolutionContext to accurately detect font traits:
@Environment(\.fontResolutionContext) var fontResolutionContext
private var isBold: Bool {
let attributes = selection.typingAttributes(in: attributedText)
if let font = attributes.font {
let resolved = font.resolve(in: fontResolutionContext)
return resolved.isBold
}
return false
}All formatting uses the modern transformAttributes(in:) API:
func toggleBold() {
attributedText.transformAttributes(in: &selection) { container in
let currentFont = container.font ?? .body
let resolved = currentFont.resolve(in: fontResolutionContext)
container.font = currentFont.bold(!resolved.isBold)
}
}Check current formatting state without accessing internal ranges:
let attributes = selection.typingAttributes(in: attributedText)
if let font = attributes.font {
// Work with font attributes
}- Uses
@Statefor local view state - Leverages SwiftUI's automatic UI updates
- Minimal state for optimal performance
- Proper use of
@Environmentfor system values - Respects iOS design patterns
ToolbarButton- Custom button with active states- Modular design for easy extension
This demo exclusively uses iOS 26+ APIs:
β
AttributedTextSelection - Modern selection handling
β
FontResolutionContext - Accurate trait detection
β
transformAttributes(in:) - Safe attribute modification
β
typingAttributes(in:) - State inspection
β
AttributedString - Rich text representation
-
Working with AttributedTextSelection
- No direct range access
- Using
typingAttributes(in:)andtransformAttributes(in:)
-
Font Trait Resolution
- Using
fontResolutionContextfor accurate detection - Proper bold/italic toggling
- Using
-
Color Management
- ColorPicker integration
- Foreground and background colors
-
Attribute Containers
- Modifying multiple attributes efficiently
- Clearing all formatting
// Example: Add superscript
func toggleSuperscript() {
attributedText.transformAttributes(in: &selection) { container in
let currentOffset = container.baselineOffset ?? 0
container.baselineOffset = currentOffset == 0 ? 5 : 0
}
}Modify the toolbar background:
.background(Color(.systemGray6)) // Change to your preferred color- iOS 26+ Only - Requires latest iOS version
- No Undo/Redo - Not implemented in this demo
- Single Font Family - Uses system font only
- No Persistence - Text is not saved between sessions
Your Name
- GitHub: @DKVekariya
- Twitter: @D_K_Vekariya
- LinkedIn: Divyesh Vekariya
- Inspired by Apple's WWDC 2024 sessions on SwiftUI
- Built following iOS 26+ design patterns
- Special thanks to the SwiftUI community
If this project helped you, please give it a βοΈ!
Built with β€οΈ using SwiftUI
Last Updated: October 2025
