如何更改标签中每 5 个第一个单词的文本颜色?

How I can change text color for every 5 first words in label?

我从 API 得到了不同的文本,我想为每 5 个第一个单词更改文本颜色。我尝试使用范围和属性字符串,但我做错了,这对我来说不是很好。我该怎么做?

这是我的代码:

private func setMessageText(text: String) {
    let components = text.components(separatedBy: .whitespacesAndNewlines)
    let words = components.filter { ![=10=].isEmpty }

    if words.count >= 5 {
        let attribute = NSMutableAttributedString.init(string: text)

        var index = 0
        for word in words where index < 5 {

            let range = (text as NSString).range(of: word, options: .caseInsensitive)
            attribute.addAttribute(NSAttributedString.Key.foregroundColor, value: Colors.TitleColor, range: range)
            attribute.addAttribute(NSAttributedString.Key.font, value: Fonts.robotoBold14, range: range)
            index += 1
        }
        label.attributedText = attribute
    } else {
        label.text = text
    }
}

enter image description here

获取第5个单词末尾的索引并为整个范围添加一次颜色和字体会更有效。

并且强烈建议您不要将 String 桥接到 NSString 以从字符串中获取子范围。 不要那样做。使用原生 Swift Range<String.Index>,有一个方便的 API 可以可靠地将 Range<String.Index> 转换为 NSRange

private func setMessageText(text: String) {
    let components = text.components(separatedBy: .whitespacesAndNewlines)
    let words = components.filter { ![=10=].isEmpty }

    if words.count >= 5 {
        let endOf5thWordIndex = text.range(of: words[4])!.upperBound
        let nsRange = NSRange(text.startIndex..<endOf5thWordIndex, in: text)

        let attributedString = NSMutableAttributedString(string: text)
        attributedString.addAttributes([.foregroundColor : Colors.TitleColor, .font : Fonts.robotoBold14], range: nsRange)
        label.attributedText = attributedString
    } else {
        label.text = text
    }
}

另一种更复杂的方法是使用带有选项 byWords

的专用 API enumerateSubstrings(in:options:
func setMessageText(text: String) {

    var wordIndex = 0
    var attributedString : NSMutableAttributedString?
    text.enumerateSubstrings(in: text.startIndex..., options: .byWords) { (substring, substringRange, enclosingRange, stop) in
        if wordIndex == 4 {
            let endIndex = substringRange.upperBound
            let nsRange = NSRange(text.startIndex..<endIndex, in: text)
            attributedString = NSMutableAttributedString(string: text)
            attributedString!.addAttributes([.foregroundColor : Colors.TitleColor, .font : Fonts.robotoBold14], range: nsRange)
            stop = true
        }
        wordIndex += 1
    }

    if let attributedText = attributedString {
       label.attributedText = attributedText
    } else {
       label.text = text
    }
}