How can I convert NSRange
to Range
in Swift?
I want to use the following UITextFieldDelegate
method:
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let strString = ((textField.text)! as NSString).stringByReplacingCharactersInRange(range, withString: string)
}
You need to use Range<String.Index>
instead of the classic NSRange
. The way I do it (maybe there is a better way) is by taking the string's String.Index
a moving it with advance
.
I don't know what range you are trying to replace, but let's pretend you want to replace the first 2 characters.
var start = textField.text.startIndex // Start at the string's start index
var end = advance(textField.text.startIndex, 2) // Take start index and advance 2 characters forward
var range: Range<String.Index> = Range<String.Index>(start: start,end: end)
textField.text.stringByReplacingCharactersInRange(range, withString: string)
I've found the cleanest swift2 only solution is to create a category on NSRange:
extension NSRange {
func stringRangeForText(string: String) -> Range<String.Index> {
let start = string.startIndex.advancedBy(self.location)
let end = start.advancedBy(self.length)
return Range<String.Index>(start: start, end: end)
}
}
And then call it from for text field delegate function:
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let range = range.stringRangeForText(textField.text)
let output = textField.text.stringByReplacingCharactersInRange(range, withString: string)
// your code goes here....
return true
}
As of Swift 4 (Xcode 9), the Swift standard
library provides methods to convert between Swift string ranges
(Range<String.Index>
) and NSString
ranges (NSRange
).
Example:
let str = "a
extension StringProtocol where Index == String.Index {
func nsRange(of string: String) -> NSRange? {
guard let range = self.range(of: string) else { return nil }
return NSRange(range, in: self)
}
}
The Swift 3.0 beta official documentation has provided its standard solution for this situation under the title String.UTF16View in section UTF16View Elements Match NSString Characters title