I'm trying to support bulleted list formatting in a UITextView in my app. I've googled around and found various answers to questions (like here) that suggest using NSParagraphStyle. Right now to make a given line bullet-formatted, I'm prepending a bullet (Unicode 2022) plus a tab (•\t) and applying a paragraph style to the line generated like this, given an indent level >= 1:
func makeBulletStyle(forLevel indentLevel: Int) -> NSParagraphStyle {
let indentInterval = 15;
let result = NSMutableParagraphStyle()
//Indent the first line of this paragraph for its indent level
result.firstLineHeadIndent = CGFloat(indentLevel * indentInterval)
let tab = NSTextTab(textAlignment: .left, location: CGFloat(indentInterval))
result.tabStops = [tab]
result.defaultTabInterval = CGFloat(indentInterval)
//Indent wrapped lines in this paragraph so they line up under the first line,
//which is indented and then tabbed. Basically firstLineHeadIndent + indentInterval
result.headIndent = CGFloat((indentLevel + 1) * indentInterval)
return result
}
This appears to work if I always use the same bullet character for the line prefix. But if I switch to using different characters for different levels, like most format-capable text editors do - empty circles, triangles, etc - then the indent and tab distances get wonky, and things don't line up anymore.
These two screenshots only change the tab characters:
What am I doing wrong here? Why do different tab characters cause issues? Right now I'm working under the admittedly shaky assumptions that:
- The indent properties and the tab properties on
NSParagraphStyleare using the same units. The docs onNSTextTab.initdon't mention units, butNSTextTabitself mentions inches.NSParagraphStyle.firstLineHeadIndentsays points.NSParagraphStyle.tabStopsmentions the default value in terms of points. - The tab distance specified with
NSTextTabis measured from thefirstLineHeadIndentposition.
I also don't quite know what role the indent interval plays here, but if I don't set it then the text on each list item ends up on the line after the bullet itself.


If you look at the NSSParagraphStyle documentation you’ll see it supports lists by use of the textLists attribute.
It also supports different list types and nested lists natively, all you need to do is add them to the property list.
Most answers you’ll find on stackoverflow about UITextView are outdated. Your best bet is to carefully read the Apple docs and watch the WWDC videos.