如何为 UITextView 中的特定单词设置样式?

How to set a style for a specific word inside UITextView?

我有一个 UITextView,我试图在其中设置特定单词的样式。我面临的问题是,在为单词设置样式时,它也会将该样式应用于该单词的所有其他出现。我只希望 say first 或 third 这个词的一个特定实例具有自定义样式。

考虑 UITextView 中的文本。

Sunset is the time of day when our sky meets the outer space solar winds. 
There are blue, pink, and purple swirls, spinning and twisting, like clouds of balloons caught in
a whirlwind. The sun moves slowly to hide behind the line of horizon, while the 
moon races to take its place in prominence atop the night sky. People slow to a crawl, 
entranced, fully forgetting the deeds that must still be done. There is a coolness, a 
calmness, when the sun does set.

如果我将样式设置为 sun,则该词的两次出现都会应用该样式。

这是代码

let normalAttr = [NSAttributedString.Key.font: UIFont(name: "Oswald", size: 19.0), NSAttributedString.Key.paragraphStyle : style]
let customAttr = [NSAttributedString.Key.font: UIFont(name: "Oswald", size: 19.0), NSAttributedString.Key.foregroundColor: UIColor.red]
let words = textView.text.components(separatedBy: " ")
let newText = NSMutableAttributedString()
for word in words {
   if (word == selectedWord) {
     newText.append(NSMutableAttributedString(string: word + " " , attributes: selectedAttributes as [NSAttributedString.Key : Any]))
   } else {
     newText.append(NSMutableAttributedString(string:word + " ", attributes: normalAttributes as [NSAttributedString.Key : Any]))
   }
 }
textView.attributedText = newText

我只想将样式应用于一个词,请问我该怎么做?

您如何选择要替换的实例?

最简单的方法是只维护您自己的计数器:

var counter = 0
for word in words {
   if (word == selectedWord) {
     counter += 1
      // myTarget being the first or third or whatever
     let attributesToUse = (counter == myTarget) ? selectedAttributes : normalAttributes
     newText.append(NSMutableAttributedString(string: word + " " , attributes: attributesToUse as [NSAttributedString.Key : Any]))
   } else {
     newText.append(NSMutableAttributedString(string:word + " ", attributes: normalAttributes as [NSAttributedString.Key : Any]))
   }
 }

但是您当然可以通过使用 NSAttributedStrings 并查找您的文本范围来变得更清晰。

let myText = NSMutableAttributedString(string: textView.text, attributes: normalAttributes)

// this will only turn up the FIRST occurrence
if let range = myText.range(of: selectedWord) {
    let rangeOfSelected = NSRange(range, in: myText)
    myText.setAttributes(selectedAttributes, range: rangeOfSelected)
}

如果你想使用任意事件,你可以写一个扩展,创建一个包含所有范围的数组,然后选择重要的一个,这是一个很好的参考:https://medium.com/@weijentu/find-and-return-the-ranges-of-all-the-occurrences-of-a-given-string-in-swift-2a2015907a0e

Def 可能有点矫枉过正,您也可以修改那些文章中的方法,改为接收一个 int (occuranceNumber) 并使用像上面那样的计数器来 return 只有范围第 n 次出现,然后对属性字符串执行相同的操作。