Search code examples
iosswiftcharacteruitextviewnsmutableattributedstring

How do I start with an empty attributedString whenever the UITextView changes?


I am using attributed string to format a single character string for UITextView that will update whenever a button is clicked or a picker is moved. However, because I use attributedStringLine.append(attributedCharString) the attributedString continues to grow rather than start a new attributed string whenever UITextViewis updated.

The code below demonstrates a simplified version of the problem.

NSMutableAttributedString() operates on the string in myArray. New strings are processed whenever UITextView changes. These are in array1, array2 and array3.

import UIKit

var str = "Hello, playground"

let array1                      = ["7.0", "55.55", "1.0", "9.27"]
let array2                      = ["0", "10", "20", "30", "40"]
let array3                      = ["A", "B", "C", "D", "E", "F"]

var myArray                     = [""]
let attributedStringLine        = NSMutableAttributedString()
let numberOfRawStringCharacters = myArray.count


func appendTextString(i: Int){
    let rangeOfCharString       = (myArray[i] as NSString).range(of: myArray[i])
    let attributedCharString    = NSMutableAttributedString.init(string: myArray[i], attributes: [NSFontAttributeName: UIFont.systemFont(ofSize: 18.0, weight: UIFontWeightLight)])
    attributedCharString.addAttributes([NSForegroundColorAttributeName : UIColor.blue], range: rangeOfCharString)
    attributedStringLine.append(attributedCharString)
}


func makeText() {
    for i in 0..<myArray.count {
        appendTextString(i: i)
    }
}

var line = attributedStringLine.length

myArray.removeAll()
myArray                         = array1
myArray.count
makeText()
print(attributedStringLine)
line = attributedStringLine.length

myArray.removeAll()
myArray                         = array2
myArray.count
makeText()
attributedStringLine
line = attributedStringLine.length

myArray.removeAll()
myArray                         = array3
myArray.count
makeText()
attributedStringLine
line = attributedStringLine.length

How do I start with an empty attributedString whenever the UITextView changes ?

For NSMutableString, replacing or deleting characters from the range of an existing attributed string seems to be the only alternative available. And I'm pretty sure this is not a duplicate of Value of type 'NSMutableAttributedString' has no member 'removeAll'


Solution

  • Since you declared attributedStringLine with let, you can remove all character from it at the start of makeText.

    func makeText() {
        attributedStringLine.deleteCharacters(in: NSMakeRange(0, attributedStringLine.length))
        for i in 0..<myArray.count {
            appendTextString(i: i)
        }
    }
    

    Or you change its declaration from let to var and then use attributedStringLine = NSMutableAttributedString() at the start of makeText.