I've just updated Xcode to 8.0 beta 2 and swift 3.0. After updating from swift 2.3 i'm getting a lot of errors.
I have a String-extension that's converting a Range in the "self"-string to a NSRange:
extension String {
func NSRangeFromRange(_ range : Range<String.Index>) -> NSRange {
let utf16view = self.utf16
let from = String.UTF16View.Index(range.lowerBound, within: utf16view)
let to = String.UTF16View.Index(range.upperBound, within: utf16view)
print("to: \(to) from: \(from)")
print(self.characters.count)
return NSMakeRange(utf16view.startIndex.distance(to: from), from.distance(to: to))
// return NSMakeRange(0, 0) // <-- removes exception
}
}
When NSMakeRange is executed I'm getting a error:
Terminating app due to uncaught exception 'NSRangeException', reason: 'NSMutableRLEArray objectAtIndex:effectiveRange:: Out of bounds'
When I'm printing the to- and from-index's, I'm getting:
to: Index(_offset: 194) from: Index(_offset: 181)
The character-count of the String is 210
, which seems about right.
So, I don't get why it's telling me that the index's are out of bounds, when they are less that the total count.
This line was working perfectly before I updated to swift 3. Back then it was looking like this:
return NSMakeRange(utf16view.startIndex.distanceTo(from), from.distanceTo(to))
The auto-converter didn't update the syntax from swift 2.3 to 3.0, I did that myselves..
Any clues?
In Swift 3, "Collections move their index", see A New Model for Collections and Indices on Swift evolution.
In Swift 2.2, the
advancedBy()
anddistanceTo()
methods are called on the index:This methods still exist in Swift 3 but give unexpected results, at least on character collections:
The correct way is to use the
index()
anddistance()
methods of the collection itself:Applied to your problem, this is how you can convert a
Range<String.Index>
to the correspondingNSRange
in Swift 3 (copied from https://stackoverflow.com/a/30404532/1187415):And for the sake of completeness, this is the opposite conversion