2016-11-10 40 views
4

这是一个跟进这个问题How can I change style of some words in my UITextView one by one in Swift?如何在我的textView中更改预选词的样式?

感谢@约什的帮助,我写的一段代码,可以突出与#开头单词 - 而且做一个接一个。我对于最终的代码是:

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"],我怎么可以把它代替正则表达式匹配的在我的代码?

+0

你有什么话对的阵列匹配方面到目前为止已经试过?自从我的单词列表 –

+0

@Patrick很短(我有一个5人6)我试图修改正则表达式,但它并不能很好的工作,因为换句话说也被捉住。我也试图直接提供的话'matches',但随后的进一步逻辑没有工作 – user3766930

回答

0

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

要配合原有的功能,你会发现你需要再次搜索,从范围月底开始,看看是否有另一场比赛在你随后的源文本匹配的范围之后。

+0

感谢,这听起来很合理,你能提供一些代码的例子吗? – user3766930

3

我相信你正在使用正则表达式来获得NSRange阵列。在这里,你需要一个稍微不同的数据结构,如[String : [NSRange]]。然后你可以使用rangeOfString功能检测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对于存储在字典中的每个单词,你可以在你UITextView因此显示的每个字。

随意,如果您有关于执行任何疑问:)发表评论

0

提出的解决方案到目前为止建议你去通过每一个单词,然后在文本视图搜索。这是有效的,但是你多次遍历文本。

我的建议是枚举文本中的所有单词,看看他们是否匹配任何的话来强调:

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() 
    } 
} 

这应该是适合于小文本。对于长文本,每次更改都要经历一切,这可能会严重影响性能。在这种情况下,我建议使用自定义的NSTextStorage子类。在那里,您可以更好地控制哪些文本的范围发生了变化,并将突出显示仅应用于该部分。

相关问题