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.

