Convert String.Index to Int or Range<String.Index> to NSRange

If you look into the definition of String.Index you find:

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
}

So actually there is no way to convert it to Int and that for good reason. Depending on the encoding of the string the single characters occupy a different number of bytes. The only way would be to count how many successor operations are needed to reach the desired String.Index.

Edit The definition of String has changed over the various Swift versions but it's basically the same answer. To see the very current definition just CMD-click on a String definition in XCode to get to the root (works for other types as well).

The distanceTo is an extension which goes to a variety of protocols. Just look for it in the String source after the CMD-click.


I don't know which version introduced it, but in Swift 4.2 you can easily convert between the two.

To convert Range<String.Index> to NSRange:

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

To convert NSRange to Range<String.Index>:

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

Keep in mind that NSRange is UTF-16 based, while Range<String.Index> is Character based. Hence you can't just use counts and positions to convert between the two!


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

Tags:

String

Swift