Swift String
aralıkları ve NSString
aralıkları "uyumlu" değildir. Örneğin, 😄 benzeri bir emoji bir Swift karakteri olarak, ancak iki NSString
karakter (UTF-16 vekil çifti olarak adlandırılır) olarak sayılır .
Bu nedenle, dize bu tür karakterler içeriyorsa, önerilen çözümünüz beklenmedik sonuçlar üretir. Misal:
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)
Çıktı:
ParaUzun paragra {
} ph demek {
NSColor = "NSCalibratedRGBColorSpace 1 0 0 1";
} İng! {
}
Gördüğünüz gibi, "ph say", "say" ile değil, niteliğiyle işaretlenmiştir.
Yana NS(Mutable)AttributedString
sonuçta bir gerektiriyor NSString
ve bir NSRange
, o verilen dize dönüştürmek için aslında iyidir NSString
ilk. Sonra substringRange
bir NSRange
ve artık aralıkları dönüştürmek zorunda değilsiniz:
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)
Çıktı:
ParagraphUzun paragraf {
} Diyerek {
NSColor = "NSCalibratedRGBColorSpace 1 0 0 1";
}! {
}
Swift 2 için güncelleme:
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)
Swift 3 için güncelleme:
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)
Swift 4 için güncelleme:
Swift 4'ten (Xcode 9) itibaren, Swift standart kütüphanesi Range<String.Index>
ve arasında dönüştürme yöntemi sağlar NSRange
. Dönüştürmek NSString
artık gerekli değil:
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)
İşte substringRange
bir olduğunu Range<String.Index>
ve bu karşılık gelen dönüştürülür NSRange
ile
NSRange(substringRange, in: text)