apple-text-layout-manager-selection
Use when choosing between TextKit 1 and TextKit 2, evaluating migration risk, or comparing NSLayoutManager vs NSTextLayoutManager
Layout Manager Selection Guide
Use this skill when the main question is whether the editor should use TextKit 1 or TextKit 2.
When to Use
- You are choosing between
NSLayoutManagerandNSTextLayoutManager. - You are evaluating migration risk or performance tradeoffs.
- You need a recommendation tied to feature requirements.
Quick Decision
Need glyph-level access?
YES → NSLayoutManager (TextKit 1)
Need multi-page/multi-column layout?
YES → NSLayoutManager (TextKit 1)
Need text tables (NSTextTable)?
YES → NSLayoutManager (TextKit 1)
Need Writing Tools inline experience?
YES → NSTextLayoutManager (TextKit 2)
Document > 10K lines and performance-critical?
→ Read the Performance Evidence section carefully
Reliable syntax highlighting via temporary attributes?
→ NSLayoutManager (TextKit 1) — TK2 renderingAttributes have known bugs
Targeting iOS 15?
→ NSLayoutManager (TextKit 1) — UITextView defaults to TK1 on iOS 15
Building new app, iOS 16+, none of the above?
→ TextKit 2 is the default and a good starting point.
Core Guidance
The Two Layout Managers
| Aspect | NSLayoutManager (TK1) | NSTextLayoutManager (TK2) |
|---|---|---|
| Available | iOS 7+ / macOS 10.0+ | iOS 15+ / macOS 12+ |
| Layout model | Contiguous (optional non-contiguous) | Always non-contiguous (viewport) |
| Abstraction | Glyph-based | Element/fragment-based |
| Text containers | Multiple | Single only |
| Performance model | O(document) or O(visible) | O(viewport) theoretical |
| International text | Manual glyph handling | Correct by design |
| Writing Tools | Panel only | Full inline |
| Custom rendering | Subclass + drawGlyphs | Subclass NSTextLayoutFragment |
| Overlay styling | Temporary attributes | Rendering attributes |
| Printing | Full support | Limited (iOS 18+) |
Performance Evidence
Apple's Claims (WWDC21)
"TextKit 2 is extremely fast for an incredibly wide range of scenarios, from quickly rendering labels that are only a few lines each to laying out documents that are hundreds of megabytes being scrolled through at interactive rates."
Developer Experience (Real-World)
ChimeHQ TextViewBenchmark (macOS 14 beta):
"TextKit 1 is extremely fast and TextKit 2 actually even a small amount faster."
For comparable document sizes on recent macOS, TextKit 2 has reached parity or slightly better.
Large document scrolling (Apple Developer Forums, multiple reports):
- TextKit 2 scrolling performance degrades above ~3,000 lines
- 10K+ lines described as "an absolute nightmare" with TextKit 2
- Switching to TextKit 1 restored smooth scrolling with 1 million characters
- These reports are primarily from iOS 16/17 era; improvements in each release
Memory usage (developer measurement):
- ~0.5 GB with TextKit 1 custom labels
- ~1.2 GB with TextKit 2 for same content
- TextKit 2's immutable object model (NSTextLayoutFragment, NSTextLineFragment) has overhead
Apple's own apps:
- Pages, Xcode, Notes: still use TextKit 1 (as of reports through 2025)
- TextEdit: uses TextKit 2 but falls back for tables, page layout, printing
Short Text (Labels, Chat Bubbles)
TextKit 2 wins here:
- No performance penalty for viewport management on short text
- Correctness benefits for international text
- Modern API with rendering attributes
Large Documents (10K+ lines)
Mixed results:
- Theoretical advantage: Viewport layout should scale to any document size
- Practical issues: Scroll bar jiggle (estimated heights), jump-to-position inaccuracy, height estimation instability
- Improving per OS release: macOS 14+ shows near-parity in benchmarks
- Recommendation: Test on your target OS version with your actual content
Line Counting
Both systems struggle with this:
- TextKit 1:
numberOfGlyphs+ enumeration. Requires full layout withallowsNonContiguousLayout = false, or approximate with non-contiguous. - TextKit 2: Must enumerate ALL layout fragments with
.ensuresLayout. Defeats viewport optimization.
For either system: Consider maintaining a separate line count (incremental update on edit) rather than querying the layout system.
TextKit 1 Is Not Deprecated
NSLayoutManager is a fully supported, non-deprecated API. Apple has not deprecated the class or its core methods. Apple's own apps (Pages, Xcode, Notes) still use TextKit 1 as of 2025. TextEdit uses TextKit 2 but falls back to TextKit 1 for tables, page layout, and printing.
TextKit 1 is not "legacy mode to maintain until you can migrate." It is the correct choice when your requirements include features that TextKit 2 does not support.
When TextKit 1 Is the Right Choice
- Glyph-level access — Custom glyph substitution, glyph inspection, typography tools. TextKit 2 has zero glyph APIs; you'd need to drop to Core Text.
- Multi-page/multi-column layout — NSTextLayoutManager supports only one container. No workaround exists.
- Text tables — NSTextTable/NSTextTableBlock are TextKit 1 only (macOS). Text tables in content trigger automatic fallback.
- Syntax highlighting via temporary attributes —
addTemporaryAttributeis rendering-only and well-tested. TextKit 2'ssetRenderingAttributeshas known drawing bugs (FB9692714) and requires customNSTextLayoutFragmentsubclasses as a workaround. - Printing — TextKit 2 has limited printing support (iOS 18+/macOS 15+) but still falls back for multi-page pagination.
- Custom NSLayoutManager subclass — Significant investment in
drawGlyphs,drawBackground, delegate methods shouldGenerateGlyphsdelegate — No TextKit 2 equivalent- Exact document height required — TextKit 1 contiguous layout gives exact height; TextKit 2 estimates
- Scroll bar accuracy critical — TextKit 2's estimated heights cause scroll bar instability
- Targeting iOS 15 — UITextView defaults to TextKit 1 on iOS 15. ~2-3% of devices as of early 2026, but significant for apps with broad reach.
When TextKit 2 Is the Right Choice
- New iOS 16+ app — It's the default; fighting it adds complexity
- Writing Tools (full inline) — Requires TextKit 2
- International text correctness — Arabic, Devanagari, CJK handled correctly without glyph assumptions
- Custom rendering via fragments — Cleaner API than drawGlyphs subclassing
- Short text (labels, chat bubbles) — No downside, cleaner API
- Viewport-based display of large content — When you don't need exact document metrics
- Custom text elements — NSTextContentManager subclass for non-attributed-string backends
Migration Decision Framework
Don't Migrate If:
- App works well with TextKit 1
- You rely on glyph APIs extensively
- You need multi-container layout
- No specific TextKit 2 feature is required
- Target OS includes iOS 15 or earlier
Consider Migrating If:
- Users need Writing Tools inline experience
- International text rendering issues in TextKit 1
- Building new text features from scratch
- Want viewport performance for very large documents
- Need rendering attributes (cleaner than temporary attributes)
Migration Strategy
- Check
textLayoutManagerfirst — write all new code to check TextKit 2 availability - Dual code paths — support both TK1 and TK2 during transition
- Test fallback — ensure your app handles fallback gracefully
- Migrate incrementally — one feature at a time, not big bang
// Dual code path pattern
if let textLayoutManager = textView.textLayoutManager {
// TextKit 2 path
textLayoutManager.enumerateTextLayoutFragments(from: nil, options: [.ensuresLayout]) { fragment in
// ...
return true
}
} else {
// TextKit 1 fallback
let layoutManager = textView.layoutManager!
layoutManager.ensureLayout(for: textView.textContainer)
// ...
}
Common Pitfalls
- Migrating without a reason — TextKit 1 works. Don't fix what isn't broken.
- Assuming TextKit 2 is always faster — Real-world performance depends on document size, OS version, and use case.
- Not testing on target OS — TextKit 2 performance improves each release. Test on YOUR minimum deployment target.
- Full-document
ensureLayoutin TextKit 2 — Defeats viewport optimization. O(document_size). - Expecting exact scroll metrics from TextKit 2 — Estimated heights cause scroll bar instability. If exact metrics matter, use TextKit 1.
Related Skills
- Use
/skill apple-text-textkit1-refor/skill apple-text-textkit2-refafter you know which stack you need. - Use
/skill apple-text-fallback-triggerswhen compatibility mode is driving the decision. - Use
/skill apple-text-viewswhen the real question is control choice, not layout-manager internals.