ProgrammingiOS Developer

What is subscripting in Swift and how to implement a custom subscript for your own structure?

Pass interviews with Hintsage AI assistant

Answer.

Background:

A subscript is a mechanism for accessing values inside collections, structures, and other types using square bracket syntax. It was added to Swift by analogy with other languages (for example, indexing in Python arrays, the [] operator in C++/Java) to make working with collections and similar objects more intuitive.

Issue:

Not all types support index access by default like arrays. When we have a structure or class with data, accessing elements often makes more sense to implement through familiar syntax (like myObject[index]), rather than through a method.

Solution:

Swift allows implementing a subscript for any custom type. It can be made read-only or read/write. Here’s an example of a structure implementing a subscript for working with a square matrix:

struct Matrix { let size: Int private var grid: [Int] init(size: Int) { self.size = size self.grid = Array(repeating: 0, count: size * size) } subscript(row: Int, column: Int) -> Int { get { precondition(indexIsValid(row, column), "Index out of range") return grid[(row * size) + column] } set { precondition(indexIsValid(row, column), "Index out of range") grid[(row * size) + column] = newValue } } private func indexIsValid(_ row: Int, _ column: Int) -> Bool { return row >= 0 && row < size && column >= 0 && column < size } } var m = Matrix(size: 3) m[1,2] = 7 print(m[1,2]) // 7

Key features:

  • A subscript can take any number of arguments, not just a single index
  • Implemented using the keyword subscript and can be either get-only or get/set
  • Allows creating a convenient and readable API for custom collections or structures

Trick Questions.

Can subscripts only be used for collections?

No, subscripts can be implemented for any type: structure, class, enum. The data type inside does not need to be a collection; the main thing is the logic for handling requests through the subscript.

Can you have multiple subscripts with different signatures in one type?

Yes, it is allowed to overload the subscript with different parameter signatures:

struct Example { subscript(index: Int) -> Int { return index } subscript(key: String) -> String { return key.uppercased() } }

Is it allowed to use a subscript as a computed property without set?

Yes, a subscript can be read-only (get-only), then an attempt to write will cause a compilation error.

struct ReadOnly { subscript(index: Int) -> Int { index * index } }

Common Errors and Anti-Patterns

  • Lack of index range checking (Index out of range)
  • Violating the “single responsibility” principle — the subscript contains business logic, not just access to data
  • Too complex and unclear subscript signatures

Real-life Example

Negative Case

In a large structure, a subscript is implemented without range checking, leading to application crashes on incorrect indices.

Pros:

  • Fast prototyping
  • Less code

Cons:

  • High likelihood of runtime crashes
  • Difficulties debugging due to unclear errors

Positive Case

Matrix is implemented with a precondition on index ranges. Any error is caught immediately, not hitting production.

Pros:

  • Safety in handling inputs
  • Easy diagnosis and maintenance

Cons:

  • Slightly more code and checks, but reliability is higher