I’ve been working on a native code editor for iPhone and iPad, and one of the more interesting problems has been making Swift files comfortable to read and edit without reprocessing the entire document after every keystroke.
The editor uses UIKit and TextKit 2, with a custom NSTextContentStorage implementation managing the source text and attributed rendering.
For syntax highlighting, I use a Swift TextMate grammar and store the parsed output in a token tree. The initial document load parses the complete file, while interactive edits are handled incrementally.
After an edit, the editor:
Invalidates the affected syntax range.
Continues parsing from the nearest valid state.
Propagates highlighting changes in bounded chunks.
Applies attributes only to ranges that need rendering.
Cancels stale work when another edit changes the document revision.
Keeping a syntax revision number turned out to be important.…