Adding Markers to Text Lists when Pressing the Return Key

December 12th, 2016

Filed under: Cocoa, Mac Development | Be the first to comment!

I tried using Apple’s NSTextList class for creating ordered and unordered lists in an application I’m developing. I was able to create lists, but when I pressed the Return key inside an unordered list, no bullet was added.

Because of this flaw in NSTextList I decided to implement my own class for lists. But I still needed to insert markers when pressing the Return key inside the list. There is very little information available on how to insert list markers when pressing the Return key so I’m sharing what I’ve learned.

Perform the following steps to insert list markers when the Return key is pressed:

  1. Create a subclass of NSTextView.
  2. Override the function insertNewline in your NSTextView subclass. This function gets called when someone presses the Return key.
  3. Use the text view’s selectedRange property to determine if you’re inside a list. The selectedRange property’s location field is the text view’s insertion point.
  4. If you’re inside a list, add the marker to the text view’s text storage at the insertion point.

The following Swift code shows a simple example of overriding insertNewline to insert a bullet when someone presses the Return key inside an unordered list:

override func insertNewline(_ sender: Any?) {
    // Choose Edit > Emoji & Symbols in Xcode to enter the bullet character.
    let bullet = "•\t"
    let bulletToAdd = NSAttributedString(string: bullet)
    if insideAList() {
        addMarker(marker: bulletToAdd, point: (selectedRange().location))

func addMarker(marker: NSAttributedString, point: Int) {
    textStorage!.insert(marker, at: point)

You’ll notice I didn’t provide the code for the insideAList function. That code depends on your application and how you store lists in the application. You have to get the ranges for the lists in your document. Check if the text view’s insertion point is in one of the ranges.


Leave a Reply

Your email address will not be published. Required fields are marked *