无法将类型“Range<String.Index>”(又名“Range<String.CharacterView.Index>”)的值转换为预期的参数类型“NSRange”(又

Posted

技术标签:

【中文标题】无法将类型“Range<String.Index>”(又名“Range<String.CharacterView.Index>”)的值转换为预期的参数类型“NSRange”(又名“_NSRange”)【英文标题】:Cannot convert value of type 'Range<String.Index>' (aka 'Range<String.CharacterView.Index>') to expected argument type 'NSRange' (aka '_NSRange') 【发布时间】:2017-09-15 05:13:50 【问题描述】:

我正在尝试用属性字符串替换子字符串。以下是我的代码。

let searchText = self.searchBar.text!
let name = item.firstName ?? ""
let idNo = "Employee Id. \(item.employeeId ?? "NA")"

if let range = name.range(of: searchText, options: String.CompareOptions.caseInsensitive, range: nil, locale: nil)

    let attributedSubString = NSAttributedString.init(string: name.substring(with: range), attributes: [NSFontAttributeName : UIFont.boldSystemFont(ofSize: 17)])
    let normalNameString = NSMutableAttributedString.init(string: name)
    normalNameString.mutableString.replacingCharacters(in: range, with: attributedSubString)
    cell.name.attributedText = normalNameString

else

    cell.name.text = name

我收到编译时错误:

“无法将'Range'(又名'Range')类型的值转换为预期的参数类型'NSRange'(又名'_NSRange')”。

我应该在这里改变什么?

【问题讨论】:

name.range 可能是返回 RangereplacingCharacters 需要方法 NSRange @Jon Snow 有什么可以转换的吗?还是用不同的方法替换? 我尝试使用 NSString 作为 name,id 但得到不同的编译错误 比较NSRange from Swift Range? 【参考方案1】:

您可以使用NSStringNSRange,也需要更改这一行normalNameString.mutableString.replacingCharacters(in: range, with: attributedSubString) 并改用这一行 normalNameString.replaceCharacters(in: nsRange, with: attributedSubString) 因为 mutableString 是 NSMutableString,而 replacingCharacters 期望 String而不是NSAttributtedString

完整代码(针对 Swift5 更新)

    let nsRange = NSString(string: name).range(of: searchText, options: String.CompareOptions.caseInsensitive)

    if nsRange.location != NSNotFound
    
        let attributedSubString = NSAttributedString.init(string: NSString(string: name).substring(with: nsRange), attributes: [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 17)])
        let normalNameString = NSMutableAttributedString.init(string: name)
        normalNameString.replaceCharacters(in: nsRange, with: attributedSubString)
        cell.name.attributedText = normalNameString
    
    else
    
        cell.name.text = name
    

【讨论】:

当字符串中有多个表情符号时,这将不起作用。我刚遇到这个问题。 我的另一个字符串在应用属性文本后从白色变为黑色。为什么会这样? @KrutikaSonawala 你需要添加颜色属性NSAttributedString.Key.foregroundColor:UIColor.white 应该没问题【参考方案2】:

请这样做,

首先,

extension String 

    func nsRange(from range: Range<String.Index>) -> NSRange 
        let from = range.lowerBound.samePosition(in: utf16)
        let to = range.upperBound.samePosition(in: utf16)
        return NSRange(location: utf16.distance(from: utf16.startIndex, to: from),
                       length: utf16.distance(from: from, to: to))
    

之后你就有了一个这样的标签和字符串,

private func setAttributedLabel() 

    let lableText = UILabel()

    let strTitle = "Basic string Double tap" // your main string
    let title:NSMutableAttributedString = NSMutableAttributedString(string: strTitle)

    // give attribute to basic string
    title.addAttributes([NSForegroundColorAttributeName:UIColor.blue ,NSFontAttributeName:UIFont.boldSystemFont(ofSize: 15)], range: NSRange.init(location: 0, length: title.length))
    lableText.attributedText = title

    // give attribute to your range string
    let rangeOfString = lableText.text?.range(of: "Double tap") // this string is subString of strTitle
    title.addAttributes([NSForegroundColorAttributeName:UIColor.gray,NSFontAttributeName:UIFont.systemFont(ofSize: 15)], range: strTitle.nsRange(from: rangeOfString!))
    lableText.attributedText = title


我希望它会有所帮助。

【讨论】:

【参考方案3】:

您必须使用Range&lt;String.index&gt; lowerBoundUpperBound 位置值创建NSRange 实例,如下所示。

let searchText = "Kiran"
let name = "Kiran Jasvanee"
let idNo = "Employee Id. \("24")"

if let range = name.range(of: searchText, options: String.CompareOptions.caseInsensitive, range: nil, locale: nil)

    let attributedSubString = NSAttributedString.init(string: name.substring(with: range), attributes: [NSFontAttributeName : UIFont.boldSystemFont(ofSize: 17)])
    let normalNameString = NSMutableAttributedString.init(string: name)

    let startPos = name.distance(from: searchText.characters.startIndex, to: range.lowerBound)
    let nsrange = NSMakeRange(startPos, searchText.characters.count)

    normalNameString.replaceCharacters(in: nsrange, with: attributedSubString)
    labelName.attributedText = normalNameString

else

    labelName.text = name
  

searchtext constant 中添加self.searchBar.text! 而不是"Kiran" 根据您的要求在name constant 中添加item.firstName ?? "" 而不是"Kiran Jasvanee"

我已经在演示中尝试过,我发布的代码如下所示。请查收。

如果name = "AKiranJasvanee" 如果name = "KiranJasvanee"

【讨论】:

【参考方案4】:

在 Swift 中,Range 不是 NSRange 类型。在这里,您将传递 Swift Range 类型,而 NSRange 是预期的,这就是您收到错误的原因。

一种解决方法是您可以将name 转换为NSString 以获得NSRange 类型的范围,如下所示:

let range = (name as NSString).range(of: searchText, options: String.CompareOptions.caseInsensitive)

let subString = NSString(string: name).substring(with: range)
let attributedSubString = NSAttributedString.init(string:subString, attributes: [NSFontAttributeName : UIFont.boldSystemFont(ofSize: 17)])
let normalNameString = NSMutableAttributedString.init(string: name)
normalNameString.replaceCharacters(in: range, with: attributedSubString)

【讨论】:

这一行normalNameString.mutableString.replacingCharacters(in: range, with: attributedSubString) 也会抛出一个错误,因为你使用attributedSubString 作为String 而是NSAttributedString

以上是关于无法将类型“Range<String.Index>”(又名“Range<String.CharacterView.Index>”)的值转换为预期的参数类型“NSRange”(又的主要内容,如果未能解决你的问题,请参考以下文章

C# 无法将类型为“System.Byte[]”的对象强制转换为类型“System.Data.DataTable

无法将类型“[PHAsset]”的值分配给类型“UIImageView!”

无法将 [Struct] 类型的值快速转换为 [string] 类型

无法将类型“()”的值转换为预期的参数类型“字符串”

无法将“字符串”类型的值转换为预期的参数类型 [任何]

无法将值类型“()”分配给字符串类型?