Development · Tip
Chat UI Architecture on iOS: SwiftUI List to UICollectionView
Engineering guide for building high-performance, streaming-friendly iOS chat message lists.
A practical architecture note outlining the migration path for an iOS chat interface from SwiftUI List down to UICollectionView. It details performance bottlenecks around keyboard handling, layout flicker, and dynamic cell sizing during token streaming, showing why embedding a UIHostingController inside a custom UICollectionViewCell outperforms UIHostingConfiguration.
How it works
Ondrej Korol's chat-UI journey for a companion app: 1) Started with SwiftUI List for speed — but chat is the core experience and must feel right; keyboard handling was the worst. 2) LazyVStack with ScrollView helped but content flickered. 3) Switched to UITableView: much better performance, fine-grained scroll position tracking, scroll-view dragging handling, still using SwiftUI views for message content via UIHostingConfiguration — but odd issues with cell insertion and keyboard inset behavior. 4) Moved to UICollectionView with Diffable Data Source and Compositional Layout — big improvement. 5) Replacing native Text with a wrapped UITextView (markdown via NSAttributedString, text selection) caused weird cell sizing and jumpiness while streaming a response. 6) Fix: instead of passing UIHostingConfiguration to contentConfiguration, use UICollectionViewCell with a UIHostingController — "it just WORKS": SwiftUI views for most cell components with much better performance.
What it's for
- Prevent cell layout jumpiness while streaming markdown or LLM tokens
- Avoid keyboard handling bugs and stutter common in pure SwiftUI message lists
- Integrate selectable UITextView markdown renderers inside hybrid UIKit and SwiftUI lists
- Choose the right iOS list container when building conversational or AI companion apps
Key points
- Identifies keyboard handling and scrolling feel issues with pure SwiftUI List
- Highlights flickering pitfalls when using ScrollView with LazyVStack
- Evaluates UITableView tradeoffs regarding cell insertion and keyboard insets
- Explains dynamic sizing bugs when streaming responses inside UIHostingConfiguration
- Provides the fix: embedding UIHostingController inside a standard UICollectionViewCell
Pricing
Free
Details
- Type
- Tip
- Category
- Development
- Topic
- iOS Development
- Open source
- No
- Platforms
- iOS
- For
- iOS engineers building chat and AI streaming interfaces
- Tags
- ios, swift, swiftui, uikit, chat ui, performance
Why it was saved
- @ondrejkorol: Concrete migration path with failure modes: SwiftUI List fails on feel/keyboard; LazyVStack flickers; UITableView fixes performance; streaming markdown text in UIHostingConfiguration cells causes cell-sizing jumpiness; UIHostingController in UICollectionViewCell fixes it.
Related
Deep-dive writeup and open-source release of the Apple Design Award–winning fitness tracker.
Pattern for building a multi-state morphing button in SwiftUI
Sample SwiftUI app demonstrating Clean Architecture with modern Swift patterns
Index official Apple documentation as reference docs inside Cursor's AI composer
SwiftUI guide for creating animated OTP verification inputs with validation states
Performance pattern for deferring below-the-fold components to accelerate perceived page load.
Updated