Swift Overview - Range

A Range in Swift is just two end points. A Range can represent things like a selection in some text or a portion of an Array.

A pseudo-representation of Range looks like this...

struct Range<T> {  
    var startIndex: T
    var endIndex: T
}

The T is restricted a little bit and must be comparable. That's because Range needs to be able to make sure that the startIndex is less than the endIndex, so every index value in Range must be able to be compared.

There are other more capable Ranges like CountableRange. A CountableRange contains consecutive values which can be iterated over or indexed into.

In fact if the type of the upper and lower bound is an Int (more specifically is "strideable" by Int) swift makes it a CountableRange. Which in turn becomes a sequence which is enumeratable with for in.

for i in 0..<20 { ... }  

Floating point numbers are an example of a type that doens't stride by Int, they stride by a floating point value. so 0.5...15.25 is just a Range, not a CountableRange which is needed for a for in.

But there is a global function called stride that will create a CountableRange from floating point values. It takes a from and through argument to specify where to start and stop and also a by which takes a value of what to step through the sequence with.

for i in stride(from: 0.5, through: 15.25, by: 0.3) {  
    ...
}

This is actually a type of CountableRange called ClosedCountableRange because it goes through to the last value in the sequence (15.25)

As an aside arrays of Ints and dictionaries are both sequences.

Creating A Range

Either ..< which excludes the upper bound or ... which is includes both bounds.

let array = ["a", "b", "c", "d"]  
let a = array[2...3] // ["c", "d"]  
let b = array[2..<3] // ["c"]  

Array index out of bound or a lower bound that is greater than the upper bound will produce a runtime crash

// runtime crash
let array = ["a", "b", "c", "d"]  
let c = array[6...8]  
let d = array[4...1]  

Strings

A subrange of a String is not a Range<Int> it's a Range<String.Index>

// this != "ll", and in fact won't even compile
let e = "hello"[2..<4]

// this is possible
let f = "hello"[start..<end]