我怎样才能改变我的textView预先选定的单词的风格?

这是这个问题的后续如何在Swift中逐个更改我的UITextView中某些单词的样式?

感谢@ Josh的帮助,我能够写出一段代码,突出显示每个以#开头的单词,然后逐一完成。 我最后的代码是:

 func highlight (to index: Int) { let regex = try? NSRegularExpression(pattern: "#(\\w+)", options: []) let matches = regex!.matches(in: hashtagExplanationTextView.text, options: [], range: NSMakeRange(0, (hashtagExplanationTextView.text.characters.count))) let titleDict: NSDictionary = [NSForegroundColorAttributeName: orangeColor] let titleDict2: NSDictionary = [NSForegroundColorAttributeName: UIColor.red] let storedAttributedString = NSMutableAttributedString(string: hashtagExplanationTextView.text!, attributes: titleDict as! [String : AnyObject]) let attributedString = NSMutableAttributedString(attributedString: storedAttributedString) guard index < matches.count else { return } for i in 0..<index{ let matchRange = matches[i].rangeAt(0) attributedString.addAttributes(titleDict2 as! [String : AnyObject], range: matchRange) } hashtagExplanationTextView.attributedText = attributedString if #available(iOS 10.0, *) { let _ = Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { _ in self.highlight(to: index + 1) } } else { DispatchQueue.main.asyncAfter(deadline: .now() + 1) { self.highlight(to: index + 1) } } } 

这工作正常,但我想改变逻辑,以便它不会突出显示#字,但突出显示(单个字)从这些单词的预先选定的单词。

所以我有这个数组var myArray:[String] = ["those","words","are","highlighted"] ,我怎么能把它代替正则expression式在我的代码匹配?

我相信你正在使用正则expression式来获得一个NSRange数组。 在这里,你需要一个稍微不同的数据结构,如[String : [NSRange]] 。 然后你可以使用rangeOfString函数来检测NSRange所在的NSRange 。 你可以按照下面给出的例子来做:

 let wordMatchArray:[String] = ["those", "words", "are", "highlighted"] let labelText:NSString = NSString(string: "those words, those ldsnvldnvsdnds, are, highlighted,words are highlighted") let textLength:Int = labelText.length var dictionaryForEachWord:[String : [NSRange]] = [:] for eachWord:String in wordMatchArray { var prevRange:NSRange = NSMakeRange(0, 0) var rangeArray:[NSRange] = [] while ((prevRange.location + prevRange.length) < textLength) { let start:Int = (prevRange.location + prevRange.length) let rangeEach:NSRange = labelText.range(of: eachWord, options: NSString.CompareOptions.literal, range: NSMakeRange(start, textLength-start)) if rangeEach.length == 0 { break } rangeArray.append(rangeEach) prevRange = rangeEach } dictionaryForEachWord[eachWord] = rangeArray } 

现在你已经有了一个NSRange数组, NSRange就是每个单词存储在字典中的[NSRange],你可以在你的UITextView相应地突出显示每个单词。

随意评论,如果你有任何疑问的实施:)

对于这个新的需求,你不需要一个正则expression式,你可以迭代你的单词数组,并使用rangeOfString找出该string是否存在,并设置定位范围的属性。

要匹配原始function,在find匹配范围后,您需要再次search,从该范围的末尾开始,查看源文本中是否有其他匹配项。

到目前为止提出的解决schemebuild议您浏览每个单词,然后在文本视图中search它们。 这是有效的,但是你遍历文本的方式太多了。

我想build议的是列举文本中的所有单词,看看它们是否匹配任何单词来突出显示:

 class ViewController: UIViewController { @IBOutlet var textView: UITextView! override func viewDidLoad() { super.viewDidLoad() textView.delegate = self highlight() } func highlight() { guard let attributedText = textView.attributedText else { return } let wordsToHighlight = ["those", "words", "are", "highlighted"] let text = NSMutableAttributedString(attributedString: attributedText) let textRange = NSRange(location: 0, length: text.length) text.removeAttribute(NSForegroundColorAttributeName, range: textRange) (text.string as NSString).enumerateSubstrings(in: textRange, options: [.byWords]) { [weak textView] (word, range, _, _) in guard let word = word else { return } if wordsToHighlight.contains(word) { textView?.textStorage.setAttributes([NSForegroundColorAttributeName: UIColor.red], range: range) } else { textView?.textStorage.removeAttribute(NSForegroundColorAttributeName, range: range) } } textView.typingAttributes.removeValue(forKey: NSForegroundColorAttributeName) } } extension ViewController: UITextViewDelegate { func textViewDidChange(_ textView: UITextView) { highlight() } } 

这对小文本应该没问题。 对于长篇大论来说,每一次改变都要经历一番,才能真正伤害到业绩。 在这种情况下,我build议使用自定义的NSTextStorage子类。 在那里,你可以更好地控制文本的变化范围,并只将亮点应用到该部分。