将String.Index转换为Int或将Range <string.index>转换为NSRange </string.index>

时间:2015-01-24 18:03:45

标签: string swift

因此,我发现了与将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)))
}

这当然有用,但它不是很漂亮,我宁愿避免不得不抓住一个子串而只是以某种方式使用范围本身,这可能吗?

6 个答案:

答案 0 :(得分:10)

如果你查看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来源中查找。

答案 1 :(得分:5)

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

答案 2 :(得分:2)

在Swift 4中,distanceTo()已被弃用。您可能需要将String转换为NSString才能利用其-[NSString rangeOfString:]方法,该方法会返回NSRange

答案 3 :(得分:1)

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
}

答案 4 :(得分:1)

我不知道哪个版本引入了它,但是在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的。 因此,您不能只使用计数和位置在两者之间转换!

答案 5 :(得分:0)

您可以使用此功能并在需要转换时调用它

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