Episode #211

Indenting Text with Text Kit

18 minutes
Published on March 3, 2016

This video is only available to subscribers. Get access to this video and 497 others.

Sam joins us again to cover how to change text layout dynamically as you type. He will implement a feature common in Markdown editors where typing dash followed by a space indents the list. In the process you'll learn about more of the Text Kit API. If you've ever wondered what type of work goes into building a text editor, this episode is for you!

About the Author

Sam Soffes is an experienced iOS developer and regular contributor to NSScreencast, with extensive experience in TextKit. You find Sam on Twitter.

Episode Links

Implementing the Text Storage

class IndentationTextStorage: BaseTextStorage {

    static let indentationAttributeName = "IndentationTextStorage.indentationAttribute"

    override func processEditing() {
        super.processEditing()

        let text = string as NSString
        let bounds = NSRange(location: 0, length: text.length)

        let attributeName = self.dynamicType.indentationAttributeName

        // Reset
        removeAttribute(attributeName, range: bounds)

        // Loop through lines
        text.enumerateSubstringsInRange(bounds, options: .ByLines) { [weak self] substring, range, _, _ in
            guard let line = substring else { return }

            // Add custom attribute
            if line.hasPrefix("- ") {
                self?.addAttribute(attributeName, value: 1, range: range)
            }
        }

        dispatch_async(dispatch_get_main_queue()) { [weak self] in
            self?.layoutManagers.forEach { $0.invalidateLayoutForCharacterRange(bounds, actualCharacterRange: nil) }
        }
    }
}