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 anNSRangeto a Swift range. The first argument is theNSRange, and the second one is the string you want to use the range with. If theNSRangeis 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"
}