user3766930 user3766930 - 29 days ago 11
Swift Question

How can I change style of some words in my UITextView one by one in Swift?

I have a

UITextView
with many different words next to each other. When user enters that screen I want to start highlighting some words, e.g.:

the first what he sees is a wall of text:

one two three #four five six #seven eight nine ten
eleven #twelve thirteen fourteen fifteen sixteen
some other words #example test whatever #some thing


then, after one second, the word
four
would change style (color), so he would see:

one two three #FOUR five six #seven eight nine ten
eleven #twelve thirteen fourteen fifteen sixteen
some other words #example test whatever #some thing


then, after one second, another word would highlight (and join already colored
four
):

one two three #FOUR five six #SEVEN eight nine ten
eleven #twelve thirteen fourteen fifteen sixteen
some other words #example test whatever #some thing


and so on. So after couple seconds user would see:

one two three #FOUR five six #SEVEN eight nine ten
eleven #TWELVE thirteen fourteen fifteen sixteen
some other words #EXAMPLE test whatever #SOME thing


and then the text should stay like this.
How can I achieve this?

I thought about looping through words and checking whether they equals the predefined words but I have no idea how to bite it - can you help me with that?

===== EDIT

So to makes things easier for myself I decided to mark highlighted words with
#
symbol.

I have extension to highlight all words that begin with
#
in the textView:

extension UITextView {

func formatTextInTextView() {
self.isScrollEnabled = false
let selectedRange = self.selectedRange
let text = self.text
let font = UIFont(name: "AppleSDGothicNeo-Light", size: 16.0)
let titleDict: NSDictionary = [NSFontAttributeName: font!]
// This will give me an attributedString with the desired font
let attributedString = NSMutableAttributedString(string: text!, attributes: titleDict as! [String : AnyObject])
let regex = try? NSRegularExpression(pattern: "#(\\w+)", options: [])
let matches = regex!.matches(in: text!, options: [], range: NSMakeRange(0, (text?.characters.count)!))
for match in matches {
let matchRange = match.rangeAt(0)

let titleDict: NSDictionary = [NSForegroundColorAttributeName: orangeColor]

attributedString.addAttributes(titleDict as! [String : AnyObject], range: matchRange)
}
self.attributedText = attributedString
self.selectedRange = selectedRange
self.isScrollEnabled = true
}
}


but I'm not sure how to highlight each word separately with one second delay

Answer

Use a timer. Stash matches in a property. Stash the base unhighlighted attributed string in a property. Now have your timer highlight the first match and call itself again in 1 second, highlighting up to the second match and repeat until there are no matches left.

    func highlight (to index: Int = 0) {
        guard index < matches.count else {
            return
        }
        let titleDict: NSDictionary = [NSForegroundColorAttributeName: orangeColor]
        let attributedString = NSMutableAttributedString(attributedString: storedAttributedString)
        for i in 0..< index {
            let matchRange = matches[i].rangeAt(0)
            attributedString.addAttributes(titleDict as! [String : AnyObject], range: matchRange)
        }
        self.attributedText = attributedString
        let _ = Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { _ in
            self.highlight(to: index + 1)
        }
    }