iosiphoneswiftswift3swift3.2

Error when adding a string to a NSMutableAttributedString


I have this function for adding a bullet to a textView

let bullet: String = " ● "

    func setAttributedValueForBullets(bullet: String, positionWhereTheCursorIs: Int?) {

    var textRange = selectedRange
    let selectedText = NSMutableAttributedString(attributedString: attributedText)

    if let line = positionWhereTheCursorIs {
        textRange.location = line
    }

    selectedText.mutableString.replaceCharacters(in: textRange, with: bullet)

    let paragraphStyle = createParagraphAttribute()
    selectedText.addAttributes([NSParagraphStyleAttributeName: paragraphStyle], range: NSMakeRange(textRange.location, bullet.length))

    self.attributedText = selectedText
    self.selectedRange = textRange
}

and it works when inserting a bullet to a paragraph with just one line like this

bullet with just one single line

but when I add it to a paragraph with more than one line this happen bullet with more than one line

I want it to look like in the first image, without that space in the bullet and the begining of text

I have also tried to use selectedText.insert(bullet, at: textRange.location)

instead of selectedText.addAttributes([NSParagraphStyleAttributeName: paragraphStyle], range: NSMakeRange(textRange.location, bullet.length))


Solution

  • This is essentially happening because of the space between the bullet point and the long description. If the description is too long, it will, by normal behavior, go on to it's own line, wrapping the rest of the string.

    The easiest fix for this, is to use a non-breaking unicode space character (u00A0):

    let bullet = "●\u{00A0}"
    let string = "thisisaveryveryveryveryveryveryveryveryveryverylongstring"
    textView.text = bullet + string
    

    This will result in the expected behavior, where the very long string will not break into it's own line, as it will be connected to the preceding bullet point:

    textView

    Also, if the space between the bullet and the string is too small, simply string together multiple non-breaking spaces:

    let bullet = "●\u{00A0}\u{00A0}"