Swift String
rentang dan NSString
rentang 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)AttributedString
pada akhirnya membutuhkan NSString
dan NSRange
, sebenarnya lebih baik untuk mengubah string yang diberikan NSString
terlebih dahulu. Maka itu substringRange
adalah NSRange
dan 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 NSString
tidak 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 substringRange
ini adalah Range<String.Index>
, dan yang dikonversi ke sesuai NSRange
dengan
NSRange(substringRange, in: text)