txt-nstextstorage

Subclass NSTextStorage and NSTextContentManager to implement custom text backing stores on TextKit.

2|Updated Sep 8, 2026
One-click install
npx skills add https://github.com/hanshi-notes/hanshi --skill txt-nstextstorage-hanshi-notes
Or copy as Structured Prompt for Agent▼
Please help me install this Agent Skill.
Skill: txt-nstextstorage
Source: https://github.com/hanshi-notes/hanshi/tree/main/.agents/skills/txt-nstextstorage
Command: npx skills add https://github.com/hanshi-notes/hanshi --skill txt-nstextstorage-hanshi-notes

SYSTEM DOCUMENTATION & REQUIREMENTS

💡 This Skill includes references (resource) components.

What problem does it solve? Implementing a custom text backing store (rope, piece table, gap buffer) or wiring syntax highlighting through TextKit requires correctly handling the NSTextStorage editing lifecycle, and mistakes like missing edited() calls or wrong changeInLength units cause silent corruption and hard-to-trace crashes. ## Core Features & Use Cases - NSTextStorage Subclassing: Implement the four required primitives (string, attributes, replaceCharacters, setAttributes) with correct edited() masks and UTF-16 length deltas. - Editing Lifecycle Guidance: Choose between willProcessEditing and didProcessEditing delegate hooks, batch edits with beginEditing/endEditing, and avoid running highlighting inside processEditing. - TextKit 2 Integration: Route mutations through performEditingTransaction, use NSTextContentStorageDelegate for display-only paragraph rewriting, and subclass NSTextContentManager for non-attributed-string models like ASTs or CRDTs. - Use Case: You are building a code editor on iOS or macOS and typing lags past 2k lines; this Skill explains the Swift String/NSString bridging bottleneck and how to fix it with an Objective-C subclass or a forwarding wrapper. ## Quick Start Ask the AI to show how to subclass NSTextStorage with a rope backing store and wire it into a TextKit 2 text view.

Frequently Asked Questions about txt-nstextstorage

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I subclass NSTextStorage with a custom backing store?▼

Override four primitives: string, attributes(at:effectiveRange:), replaceCharacters(in:with:), and setAttributes(_:range:). Each mutation must call edited(_:range:changeInLength:) with the correct mask, wrapped in beginEditing/endEditing, or layout managers never learn the storage changed.

Should syntax highlighting go in willProcessEditing or didProcessEditing?▼

Use didProcessEditing for attribute-only highlighting applied to committed text, and willProcessEditing for transforms that change characters or need fixAttributes to run after. Better still, highlight from textViewDidChange outside the edit transaction to avoid caret jumps.

Why is my Swift NSTextStorage subclass slow on large documents?▼

Swift subclasses trigger an O(n) String-to-NSString bridge on every .string query, and the layout manager queries per keystroke, degrading around 2k lines. Write the subclass in Objective-C or wrap a real NSTextStorage and forward calls to it.

Does NSTextStorage work with TextKit 2?▼

Yes, NSTextStorage remains the backing store on TextKit 2, with NSTextContentStorage regenerating NSTextParagraph elements from it. All mutations must be wrapped in performEditingTransaction or element regeneration and layout invalidation become unreliable.

Why does my text view not update after editing the storage?▼

The usual causes are a missing edited() call in a subclass mutation primitive, or mutating the storage on TextKit 2 without performEditingTransaction. The storage updates internally but layout managers and element regeneration never receive the change notification.

When should I subclass NSTextContentManager instead of NSTextStorage?▼

Subclass NSTextContentManager when the document model is not an attributed string, such as an HTML DOM, syntax tree, or CRDT. Current SDKs still require an NSTextStorage as a synthesized backing store, with overrides translating to and from the real model.