Swift Stringrentang dan NSStringrentang tidak "kompatibel". Misalnya, emoji seperti π dihitung sebagai satu karakter Swift, tetapi sebagai dua NSString
karakter (pasangan pengganti UTF-16).
Karena itu solusi yang Anda sarankan akan menghasilkan hasil yang tidak terduga jika string berisi karakter tersebut. Contoh:
let text = "πππLong paragraph saying!"
let textRange = text.startIndex..<text.endIndex
let attributedString = NSMutableAttributedString(string: text)
text.enumerateSubstringsInRange(textRange, options: NSStringEnumerationOptions.ByWords, { (substring, substringRange, enclosingRange, stop) -> () in
let start = distance(text.startIndex, substringRange.startIndex)
let length = distance(substringRange.startIndex, substringRange.endIndex)
let range = NSMakeRange(start, length)
if (substring == "saying") {
attributedString.addAttribute(NSForegroundColorAttributeName, value: NSColor.redColor(), range: range)
}
})
println(attributedString)
Keluaran:
Parag Paragraf panjang {
} ph katakan {
NSColor = "NSCalibratedRGBColorSpace 1 0 0 1";
} ing! {
}
Seperti yang Anda lihat, "ph say" telah ditandai dengan atribut, bukan "mengatakan".
Karena NS(Mutable)AttributedStringpada akhirnya membutuhkan NSStringdan NSRange, sebenarnya lebih baik untuk mengubah string yang diberikan NSStringterlebih dahulu. Maka itu substringRange
adalah NSRangedan Anda tidak perlu mengonversi rentang lagi:
let text = "πππLong paragraph saying!"
let nsText = text as NSString
let textRange = NSMakeRange(0, nsText.length)
let attributedString = NSMutableAttributedString(string: nsText)
nsText.enumerateSubstringsInRange(textRange, options: NSStringEnumerationOptions.ByWords, { (substring, substringRange, enclosingRange, stop) -> () in
if (substring == "saying") {
attributedString.addAttribute(NSForegroundColorAttributeName, value: NSColor.redColor(), range: substringRange)
}
})
println(attributedString)
Keluaran:
Paragraph Paragraf panjang {
}pepatah{
NSColor = "NSCalibratedRGBColorSpace 1 0 0 1";
}! {
}
Pembaruan untuk Swift 2:
let text = "πππLong paragraph saying!"
let nsText = text as NSString
let textRange = NSMakeRange(0, nsText.length)
let attributedString = NSMutableAttributedString(string: text)
nsText.enumerateSubstringsInRange(textRange, options: .ByWords, usingBlock: {
(substring, substringRange, _, _) in
if (substring == "saying") {
attributedString.addAttribute(NSForegroundColorAttributeName, value: NSColor.redColor(), range: substringRange)
}
})
print(attributedString)
Pembaruan untuk Swift 3:
let text = "πππLong paragraph saying!"
let nsText = text as NSString
let textRange = NSMakeRange(0, nsText.length)
let attributedString = NSMutableAttributedString(string: text)
nsText.enumerateSubstrings(in: textRange, options: .byWords, using: {
(substring, substringRange, _, _) in
if (substring == "saying") {
attributedString.addAttribute(NSForegroundColorAttributeName, value: NSColor.red, range: substringRange)
}
})
print(attributedString)
Pembaruan untuk Swift 4:
Pada Swift 4 (Xcode 9), perpustakaan standar Swift menyediakan metode untuk mengkonversi antara Range<String.Index>dan NSRange. Konversi ke NSStringtidak lagi diperlukan:
let text = "πππLong paragraph saying!"
let attributedString = NSMutableAttributedString(string: text)
text.enumerateSubstrings(in: text.startIndex..<text.endIndex, options: .byWords) {
(substring, substringRange, _, _) in
if substring == "saying" {
attributedString.addAttribute(.foregroundColor, value: NSColor.red,
range: NSRange(substringRange, in: text))
}
}
print(attributedString)
Berikut substringRangeini adalah Range<String.Index>, dan yang dikonversi ke sesuai NSRangedengan
NSRange(substringRange, in: text)