来自Swift Range的NSRange?

 sprout--_557 发布于 2022-12-10 13:07

问题:当我使用使用Range的Swift String时,NSAttributedString接受NSRange

let text = "Long paragraph saying something goes here!"
let textRange = text.startIndex.. () in

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

产生以下错误:

错误:'Range'不能转换为'NSRange'aligolsString.addAttribute(NSForegroundColorAttributeName,value:NSColor.redColor(),range:substringRange)

Martin R.. 241

Swift String范围和NSString范围不是"兼容的".例如,表情符号就像一个Swift字符,但是作为两个NSString 字符(所谓的UTF-16代理对).

因此,如果字符串包含此类字符,则建议的解决方案将产生意外结果 例:

let text = "Long paragraph saying!"
let textRange = text.startIndex.. () 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"已经标有属性,而不是"说".

由于NS(Mutable)AttributedString最终需要a NSString和a 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)

输出:

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

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)

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)

Swift 4的更新:

从Swift 4(Xcode 9)开始,Swift标准库提供了在Range和之间进行转换的方法NSRange.NSString不再需要转换为:

let text = "Long paragraph saying!"
let attributedString = NSMutableAttributedString(string: text)

text.enumerateSubstrings(in: text.startIndex..

substringRange是一个Range,并将其转换为相应NSRange

NSRange(substringRange, in: text)

对于想要在OSX上键入表情符号字符的任何人 - 控制 - 命令空间栏会显示一个字符选择器 (70认同)

如果我匹配多个单词,这不起作用,我不确定要匹配的整个字符串是什么.假设我从API返回一个字符串并在另一个字符串中使用它,我希望API中的字符串加下划线,我不能保证子字符串不会出现在API的字符串和其他字符串中串!有任何想法吗? (2认同)

你提到`Range `和`NSString`是不兼容的.他们的同行也不相容吗?即`NSRange`和`String`不兼容?因为Apple的API之一特别结合了两者:[matches(in:options:range:)](https://developer.apple.com/reference/foundation/nsregularexpression/1412446-matches) (2认同)


royherma.. 53

对于像你描述的那样的情况,我发现这是有用的.它相对简短而且甜美:

 let attributedString = NSMutableAttributedString(string: "follow the yellow brick road") //can essentially come from a textField.text as well (will need to unwrap though)
 let text = "follow the yellow brick road"
 let str = NSString(string: text) 
 let theRange = str.rangeOfString("yellow")
 attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.yellowColor(), range: theRange)

attributionString.addAttribute不适用于swift Range (9认同)

@Paludis,你是对的,但这个解决方案并没有尝试使用Swift系列.它使用的是"NSRange".`str`是一个`NSString`,因此`str.RangeOfString()`返回一个`NSRange`. (6认同)

你也可以删除第2行中的重复字符串,方法是将第2行和第3行替换为:`let str = attributionString.string as NSString` (3认同)


George Maisu.. 23

答案很好,但使用Swift 4可以简化代码:

let text = "Test string"
let substring = "string"

let substringRange = text.range(of: substring)!
let nsRange = NSRange(substringRange, in: text)

请注意,因为range功能的结果必须打开.

6 个回答
  • 对于像你描述的那样的情况,我发现这是有用的.它相对简短而且甜美: letattributedString=NSMutableAttributedString(string:followtheyellowbrickroad)//canessentiallycomefromatextField.textaswell(willneedtounwrapthough) lettext=followtheyellowbrickroad letstr=NSString(string:text) lettheRange=str.rangeOfString(yellow) attributedString.addAttribute(NSForegroundColorAttributeName,value:UIColor.yellowColor(),range:theRange)
    2022-12-11 01:56 回答
  • 可能解决方案

    Swift提供distance(),用于测量可用于创建NSRange的start和end之间的距离:

    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
        let start = distance(text.startIndex, substringRange.startIndex)
        let length = distance(substringRange.startIndex, substringRange.endIndex)
        let range = NSMakeRange(start, length)
    
    //    println("word: \(substring) - \(d1) to \(d2)")
    
            if (substring == "saying") {
                attributedString.addAttribute(NSForegroundColorAttributeName, value: NSColor.redColor(), range: range)
            }
    })
    

    2022-12-11 02:09 回答
  • 斯威夫特4:

    当然,我知道Swift 4已经扩展了NSRange

    public init<R, S>(_ region: R, in target: S) where R : RangeExpression,
        S : StringProtocol, 
        R.Bound == String.Index, S.Index == String.Index
    

    我知道在大多数情况下这个初始化就足够了.看它的用法:

    let string = "Many animals here:  !!!"
    
    if let range = string.range(of: ""){
         print((string as NSString).substring(with: NSRange(range, in: string))) //  ""
     }
    

    但转换可以直接从Range <String.Index>到NSRange完成而不需要Swift的String实例.

    而不是通用的init用法,它要求您将目标参数作为String,如果您没有目标字符串,则可以直接创建转换

    extension NSRange {
        public init(_ range:Range<String.Index>) {
            self.init(location: range.lowerBound.encodedOffset,
                  length: range.upperBound.encodedOffset -
                          range.lowerBound.encodedOffset) }
        }
    

    或者您可以为Range本身创建专门的扩展

    extension Range where Bound == String.Index {
        var nsRange:NSRange {
        return NSRange(location: self.lowerBound.encodedOffset,
                         length: self.upperBound.encodedOffset -
                                 self.lowerBound.encodedOffset)
        }
    }
    

    用法:

    let string = "Many animals here:  !!!"
    if let range = string.range(of: ""){
        print((string as NSString).substring(with: NSRange(range))) //  ""
    }
    

    要么

    if let nsrange = string.range(of: "")?.nsRange{
        print((string as NSString).substring(with: nsrange)) //  ""
    }
    

    2022-12-11 02:09 回答
  • 对我来说,这很完美:

    let font = UIFont.systemFont(ofSize: 12, weight: .medium)
    let text = "text"
    let attString = NSMutableAttributedString(string: "exemple text :)")
    
    attString.addAttributes([.font: font], range:(attString.string as NSString).range(of: text))
    
    label.attributedText = attString
    

    2022-12-11 02:10 回答
  • 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"已经标有属性,而不是"说".

    由于NS(Mutable)AttributedString最终需要a NSString和a 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)
    

    输出:

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

    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)
    

    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)
    

    Swift 4的更新:

    从Swift 4(Xcode 9)开始,Swift标准库提供了在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是一个Range<String.Index>,并将其转换为相应NSRange

    NSRange(substringRange, in: text)
    

    2022-12-11 02:58 回答
  • 答案很好,但使用Swift 4可以简化代码:

    let text = "Test string"
    let substring = "string"
    
    let substringRange = text.range(of: substring)!
    let nsRange = NSRange(substringRange, in: text)
    

    请注意,因为range功能的结果必须打开.

    2022-12-11 03:11 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有