스위프트 String
범위와 NSString
범위는 "호환되지 않습니다". 예를 들어, 😄와 같은 이모지는 하나의 스위프트 문자로 간주되지만 두 NSString
문자 (소위 UTF-16 서로 게이트 쌍)로 계산됩니다.
따라서 문자열에 이러한 문자가 포함되어 있으면 제안 된 솔루션에서 예기치 않은 결과가 발생합니다. 예:
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)
산출:
😄😄😄Long paragra {
} ph 말 {
NSColor = "NSCalibratedRGBColorSpace 10010 1";
} ing! {
}
보시다시피 "ph say"는 "saying"이 아닌 속성으로 표시되었습니다.
NS(Mutable)AttributedString
궁극적으로 NSString
and가 필요하기 때문에 NSRange
실제로 주어진 문자열을 NSString
먼저 변환하는 것이 좋습니다 . 그런 다음은 substringRange
이며 NSRange
더 이상 범위를 변환 할 필요가 없습니다.
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)
산출:
😄😄😄 긴 단락 {
}속담{
NSColor = "NSCalibratedRGBColorSpace 10010 1";
}! {
}
스위프트 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)
스위프트 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)
스위프트 4 업데이트 :
스위프트 4 (엑스 코드 9)로, 스위프트 표준 라이브러리 사이의 변환 방법을 제공 Range<String.Index>
하고이 NSRange
. NSString
더 이상으로 변환 할 필요가 없습니다.
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)
여기서 substringRange
A는 Range<String.Index>
, 그리고 그 대응으로 변환된다 NSRange
으로
NSRange(substringRange, in: text)