2014-11-28 8 views
10

questo codicecolori tutte le occorrenze di stringa a Swift

var textSearch="hi" 
var textToShow="hi hihi hi" 
var rangeToColor = (textToShow as NSString).rangeOfString(textSearch) 
var attributedString = NSMutableAttributedString(string:textToShow) 
attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.yellowColor() , range: rangeToColor) 
TextView.attributedText=attributedString 

mi dà NSRange per colorare una stringa all'interno del TextView. Il problema è che restituisco solo la prima occorrenza. Se la parola contiene "hi hihi hi", solo il primo "ciao" è colorato. Come posso ottenere tutte le occorrenze della stringa?

+0

tua soluzione è in Objective-C:/ – jjx

+0

ha scritto nel Swift dal http://stackoverflow.com/questions/8533691/how-to-get-all-nsrange-of-a-particular-character- in-a-nsstring? lq = 1 – Kevin

risposta

21

Swift 3

let attrStr = NSMutableAttributedString(string: "hi hihi hey") 
let inputLength = attrStr.string.characters.count 
let searchString = "hi" 
let searchLength = searchString.characters.count 
var range = NSRange(location: 0, length: attrStr.length) 

while (range.location != NSNotFound) { 
    range = (attrStr.string as NSString).range(of: searchString, options: [], range: range) 
    if (range.location != NSNotFound) { 
     attrStr.addAttribute(NSForegroundColorAttributeName, value: UIColor.yellow(), range: NSRange(location: range.location, length: searchLength)) 
     range = NSRange(location: range.location + range.length, length: inputLength - (range.location + range.length)) 
    } 
} 

Swift 2

let attrStr = NSMutableAttributedString(string: "hi hihi hey") 
let inputLength = attrStr.string.characters.count 
let searchString = "hi" 
let searchLength = searchString.characters.count 
var range = NSRange(location: 0, length: attrStr.length) 

while (range.location != NSNotFound) { 
    range = (attrStr.string as NSString).rangeOfString(searchString, options: [], range: range) 
    if (range.location != NSNotFound) { 
     attrStr.addAttribute(NSForegroundColorAttributeName, value: UIColor.yellowColor(), range: NSRange(location: range.location, length: searchLength)) 
     range = NSRange(location: range.location + range.length, length: inputLength - (range.location + range.length)) 
    } 
} 
3

zucchero sintassi per la risposta di Kevin sopra.

Chiamato come:

attrStr.attributeRangeFor(searchString, attributeValue: UIColor.yellowColor(), atributeSearchType: .All) 

Swift 2.0:

import UIKit 

extension NSMutableAttributedString { 
    enum AtributeSearchType { 
     case First, All, Last 
    } 

    func attributeRangeFor(searchString: String, attributeValue: AnyObject, atributeSearchType: AtributeSearchType) { 
     let inputLength = self.string.characters.count 
     let searchLength = searchString.characters.count 
     var range = NSRange(location: 0, length: self.length) 
     var rangeCollection = [NSRange]() 

     while (range.location != NSNotFound) { 
      range = (self.string as NSString).rangeOfString(searchString, options: [], range: range) 
      if (range.location != NSNotFound) { 
       switch atributeSearchType { 
       case .First: 
        self.addAttribute(NSForegroundColorAttributeName, value: attributeValue, range: NSRange(location: range.location, length: searchLength)) 
        return 
       case .All: 
        self.addAttribute(NSForegroundColorAttributeName, value: attributeValue, range: NSRange(location: range.location, length: searchLength)) 
        break 
       case .Last: 
        rangeCollection.append(range) 
        break 
       } 

       range = NSRange(location: range.location + range.length, length: inputLength - (range.location + range.length)) 
      } 
     } 

     switch atributeSearchType { 
     case .Last: 
      let indexOfLast = rangeCollection.count - 1 
      self.addAttribute(NSForegroundColorAttributeName, value: attributeValue, range: rangeCollection[indexOfLast]) 
      break 
     default: 
      break 
     } 
    } 
} 
+1

Allo scopo di migliorare le mie risposte in futuro, alcuni possono spiegare perché la mia risposta è stata rifiutata? L'utilizzo di un metodo di estensione mi sembra più pulito. – user1146169

+0

Grazie! Ho trovato questo un modo molto utile ed estensibile per il mio caso d'uso. Forse un dizionario potrebbe essere utilizzato per più attributi? –

0

Utilizzando NSRegularExpression puoi risparmiare dal fare tutti i calcoli gamma su da soli. Questo esempio evidenzierà due parole invece di una sola.

let text = "If you don't have a plan, you become part of somebody else's plan." 
let toHighlight = ["plan", "you"] 
let range = text.nsRange(from: text.startIndex ..< text.endIndex) // full text 

let rangesToHighlight: [[NSRange]] = toHighlight.map { search in 
    do { 
     let regex = try NSRegularExpression(pattern: search, options: []) 
     let matches: [NSTextCheckingResult] = regex.matches(in: text, options: [], range: range) 
     return matches.map { $0.range } // get range from NSTextCheckingResult 
    } catch { 
     return [NSRange]() 
    } 
} 

let yellow = UIColor.yellow 
let attributedText = NSMutableAttributedString(string: text) 

let flattenedRanges: [NSRange] = rangesToHighlight.joined() 
flattenedRanges.forEach { // apply color to all ranges 
    attributedText.addAttribute(NSForegroundColorAttributeName, 
           value: yellow, 
           range: $0) 
}