Цвет всех вхождений строки в 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
дает мне NSRange для цветной строки внутри TextView.
Проблема в том, что я возвращаю только первое вхождение.
Если слово содержит "hi hihi hi", то только первое "привет" окрашено.
Как я могу получить все вхождения строки?
Ответы
Ответ 1
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))
}
}
Ответ 2
Синтаксис сахара для Кевина отвечает выше.
Вызывается как:
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
}
}
}
Ответ 3
Использование NSRegularExpression
избавляет вас от выполнения всех вычислений диапазона самостоятельно. Этот пример также выделит два слова вместо одного.
let text = "If you don't have a plan, you become part of somebody else 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)
}