Problem: NSAttributedString接受NSRange,而我正在使用使用Range的SWIFT字符串

let text = "Long paragraph saying something goes here!"
let textRange = text.startIndex..<text.endIndex
let attributedString = NSMutableAttributedString(string: text)

text.enumerateSubstringsInRange(textRange, options: NSStringEnumerationOptions.ByWords, { (substring, substringRange, enclosingRange, stop) -> () in

    if (substring == "saying") {
        attributedString.addAttribute(NSForegroundColorAttributeName, value: NSColor.redColor(), range: substringRange)
    }
})

Produces the following error:

错误:"Range"不能转换为"NSRange" attributedString.addAttribute(NSForegroundColorAttributeName,值:NSColor.redColor(),范围:subingRange)

推荐答案

SWIFT String范围和NSString范围不"兼容". 例如,像?这样的表情符号被算作一个Swift 字符,但却被算作两个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 say{
    NSColor = "NSCalibratedRGBColorSpace 1 0 0 1";
}ing!{
}

如您所见,"ph say"已标记为属性,而不是"saying".

因为NS(Mutable)AttributedString最终需要NSStringNSRange,所以它实际上是 最好先将给定的字符串转换为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)

输出:

???Long paragraph {
}saying{
    NSColor = "NSCalibratedRGBColorSpace 1 0 0 1";
}!{
}

Update for 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)

Update for 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)

Update for Swift 4:

从Swift 4(Xcode 9)开始,Swift标准库

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)

这里substringRangeRange<String.Index>,它被转换成

NSRange(substringRange, in: text)

Ios相关问答推荐

两次调度Deliverc时未调用iOS GCD完成块

Xcode15.3上的生成错误:调用的对象类型';facebook::flipper::SocketCertificateProvider';不是函数或函数指针

如何在 Android 上的 Flutter 应用中录制内部音频?

为什么在Actor内部使用withTaskGroupwork并行运行?

小部件链接有效,但不执行任何操作

Xcode 13.4.1 (13F100)Command CodeSign 失败,退出代码非零我应该删除哪个证书?

SwiftUI DatePicker 格式在每个设备上都不一样,如何让它总是显示相同的 Select 版本?

如何识别 SwiftUI 中点击的按钮 ID 以使该按钮动画化?

在向我的 struct 添加属性后获取线程 10:EXC_BAD_ACCESS (code=EXC_I386_GPFLT)

如何在 Swift 中从另一个视图控制器将元素附加到数组中

如何将标准化坐标系中的点的位置转换为具有相对位置的常规坐标系?

iPhone 6 和 6 Plus 媒体查询

UICollectionView - 动态单元格高度?

在 iOS 7 上更改标签栏色调 colored颜色

在 iOS 8.1 模拟器上更改语言不起作用

如何将自己项目中的类导入 Playground

UIView 中的 safeAreaInsets 在 iPhone X 上为 0

如何删除UITableView中最后一个单元格的最后一个边框?

如何立即移动 CALayer(无动画)

openURL:在 iOS 10 中已弃用