Published on August 26, 2020
Byte of the Week: String Range & NSRange
In Swift, a character of a String cannot be accessed by its integer position. You need to use a more complex index type that takes Unicode character representation into account. This index type is not compatible with NSRange
, which is used by a lot of Objective-C APIs.
The good news is that the Swift Standard Library provides little-known type-safe helpers to convert a String index range to an NSRange
and vice-versa:
- Use
NSRange(_:in:)
to convert a String range to anNSRange
. The first argument is the range, and the second is the string you created the range from. - Use
Range<String.Index>(_:in:)
to convert anNSRange
to a Swift range. The first argument is theNSRange
, and the second one is the string you want to use the range with. If theNSRange
is not valid for that String, the initializer returnsnil
.
Example
// 1) Create a range in Swift
let string = "Hello World 🧑🏼💻"
let plainTextRange = string.startIndex
..< string.index(string.endIndex, offsetBy: -2)
// 2) Create an NSRange from the String range
let nsRange = NSRange(plainTextRange, in: string)
print((string as NSString).substring(with: nsRange)) // prints "Hello World"
// 3) Convert it back to a String range
if let convertedRange = Range<String.Index>(nsRange, in: string) {
print(string[convertedRange]) // prints "Hello World"
}