You're right that String
, as a Collection
, refers to position using index
. However, Swift makes a distinction between index
and offset
. What you're thinking of is an offset
, which starts at zero and increases by one after every item.
Collections don't use offsets. They instead use index
, which does not need to start at zero, e.g. ArraySlice
, and doesn't even need to be Int
, e.g. String
.
To move around, you start from a valid index (startIndex
, endIndex
) and use the Collection
's APIs, such as index(after:)
to create another, valid index. In your example, you want an item at offset one, you can fetch an index after the startIndex
:
let index = string.index(after: string.startIndex)
string[index] // B
string.unicodeScalars[index] // 66
You can mutate the valid index in-place:
var index = string.startIndex
string.formIndex(after: &index)
string[index] // B
There's also a variation to move by multiple offsets:
let index1 = string.index(string.startIndex, offsetBy: 1)
var index2 = string.startIndex
string.formIndex(&index2, offsetBy: 1)
string[index1] // B
string[index2] // B
Here's a little something, String
also adopts the concept of Views
, which means that a valid String
index is also a valid index for other collections in its possession, including unicodeScalars
, utf8
, utf16
, etc. So you can (largely) interchanges indices between different views.