VYT
VYT

Reputation: 1071

Problems with migration from swift2 to swift3 with ranges

I have strings and determine the ranges of indexes. I will need later for instance .last .count for these ranges. How should I initialise the range for string to be able to get functionality .last .count for these ranges (that is obvious in swift2 but not in swift3) ?

For example, I am often using the .count for range of string in my code in swift2, like this

var str = "Hello, playground"

let myRange = str.rangeOfString("Hello")

let myCountOfRange = myRange.count

Now it is not possible to do this in swift3

var str = "Hello, playground"

let myRange = str.range(of: "Hello")

let myCountOfRange = myRange.count // type index does not conform to protocol strideable 

Upvotes: 0

Views: 582

Answers (1)

vacawama
vacawama

Reputation: 154731

In Swift3, to find the size of a range you can do:

var str = "Hello, playground"

let myRange = str.range(of: "Hello")

let myCountOfRange = str[myRange!].characters.count

I don't know if this is the best way, but it works.

Alternatively:

let myCountOfRange = str.distance(from: myRange!.lowerBound, to: myRange!.upperBound)

Both require access to the original collection (ie. string), and that apparently is a limitation of Swift 3. The new model for collections and indices is discussed here.


If you want to store the ranges in an array and call .count and .last on them, you can convert the Range<Index> to a CountableRange<Int> while you still have access to the collection:

var str = "Hello, playground"

let myRange = str.range(of: "Hello")!

let lb = str.distance(from: str.startIndex, to: myRange.lowerBound) as Int
let ub = str.distance(from: str.startIndex, to: myRange.upperBound) as Int

let newRange = lb..<ub
newRange.count  // 5
newRange.last   // 4

Upvotes: 2

Related Questions