2016-11-10 56 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子類。在那裏,您可以更好地控制哪些文本的範圍發生了變化,並將突出顯示僅應用於該部分。

相關問題