繁体   English   中英

将 String.Index 转换为 Int 或 Range<String.Index> 到 NSR 范围

[英]Convert String.Index to Int or Range<String.Index> to NSRange

所以我发现了与将NSRange转换为Range<String.Index>的情况有关的问题,但我实际上遇到了相反的问题。

很简单,我有一个String和一个Range<String.Index>并且需要将后者转换为NSRange以与旧函数一起使用。

到目前为止,我唯一的解决方法是像这样抓取一个子字符串:

func foo(theString: String, inRange: Range<String.Index>?) -> Bool {
    let theSubString = (nil == inRange) ? theString : theString.substringWithRange(inRange!)
    return olderFunction(theSubString, NSMakeRange(0, countElements(theSubString)))
}

这当然有效,但它不是很漂亮,我宁愿避免必须获取子字符串并以某种方式使用范围本身,这可能吗?

如果您查看String.Index的定义,您会发现:

struct Index : BidirectionalIndexType, Comparable, Reflectable {

    /// Returns the next consecutive value after `self`.
    ///
    /// Requires: the next value is representable.
    func successor() -> String.Index

    /// Returns the previous consecutive value before `self`.
    ///
    /// Requires: the previous value is representable.
    func predecessor() -> String.Index

    /// Returns a mirror that reflects `self`.
    func getMirror() -> MirrorType
}

所以实际上没有办法将它转换为Int并且这是有充分理由的。 根据字符串的编码,单个字符占用不同数量的字节。 唯一的方法是计算需要多少successor操作才能达到所需的String.Index

编辑String的定义在各种 Swift 版本中发生了变化,但基本上是相同的答案。 要查看最新的定义,只需 CMD 键单击 XCode 中的String定义即可到达根目录(也适用于其他类型)。

distanceTo是适用于各种协议的扩展。 只需在 CMD 单击后在String源中查找它。

我不知道是哪个版本引入了它,但在 Swift 4.2 中,您可以轻松地在两者之间进行转换。

Range<String.Index>转换为NSRange

let range   = s[s.startIndex..<s.endIndex]
let nsRange = NSRange(range, in: s)

要将NSRange转换为Range<String.Index>

let nsRange = NSMakeRange(0, 4)
let range   = Range(nsRange, in: s)

请记住, NSRange是基于 UTF-16 的,而Range<String.Index>是基于Character的。 因此,您不能仅使用计数和位置在两者之间进行转换!

let index: Int = string.startIndex.distanceTo(range.startIndex)

在 Swift 4 中, distanceTo()已弃用。 您可能必须将String转换为NSString以利用其-[NSString rangeOfString:]方法,该方法返回一个NSRange

Swift 4 完整解决方案:

OffsetIndexableCollection(使用 Int 索引的字符串)

https://github.com/frogcjn/OffsetIndexableCollection-String-Int-Indexable-

let a = "01234"

print(a[0]) // 0
print(a[0...4]) // 01234
print(a[...]) // 01234

print(a[..<2]) // 01
print(a[...2]) // 012
print(a[2...]) // 234
print(a[2...3]) // 23
print(a[2...2]) // 2

if let number = a.index(of: "1") {
    print(number) // 1
    print(a[number...]) // 1234
}

if let number = a.index(where: { $0 > "1" }) {
    print(number) // 2
}

您可以使用此函数并在需要转换时调用它

extension String
{ 
    func CnvIdxTooIntFnc(IdxPsgVal: Index) -> Int
    {
        return startIndex.distanceTo(IdxPsgVal)
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM