ProgrammingiOS Developer

Explain the features of working with Subscripts in Swift. What restrictions exist for subscript, how can this mechanism be extended, and where should it be applied? Provide an example of a non-standard subscript.

Pass interviews with Hintsage AI assistant

Answer

Subscripts in Swift allow access to type values by a key or index in a way similar to arrays or dictionaries, but for any of your own types. The syntax is similar to a function, but access is done in brackets: object[key].

Features:

  • A class or struct can have multiple subscripts (overloading by parameters).
  • A subscript can be read-only or read-write (containing either get, or get and set).
  • A subscript can have any number of parameters and types (e.g., two indices).
  • No support for variadic parameters.

Application:

  • For simplified access to collections, matrices, custom objects, serializable values, etc.

Example: A two-dimensional array (matrix) and a subscript with two parameters:

struct Matrix { let rows: Int, columns: Int private var grid: [Double] init(rows: Int, columns: Int) { self.rows = rows self.columns = columns grid = Array(repeating: 0.0, count: rows * columns) } subscript(row: Int, column: Int) -> Double { get { precondition(isValid(row: row, column: column), "Index out of range") return grid[(row * columns) + column] } set { precondition(isValid(row: row, column: column), "Index out of range") grid[(row * columns) + column] = newValue } } private func isValid(row: Int, column: Int) -> Bool { return row >= 0 && row < rows && column >= 0 && column < columns } } var matrix = Matrix(rows: 2, columns: 2) matrix[0,1] = 5.0 print(matrix[0,1]) // 5.0

Trick question

Can a subscript have an inout parameter or be mutating in a struct?

Answer:

  • A subscript parameter cannot be inout.
  • A subscript in a value type (struct/enum) can be declared as mutating set, allowing modifications of self inside set:
struct Counter { var value: Int = 0 subscript(increment: Bool) -> Int { mutating get { value += increment ? 1 : -1 return value } } }

Examples of real errors due to ignorance of the nuances of the topic


Story

In a custom collection, they forgot to make the set in the mutating subscript in the struct, resulting in any attempt to modify an element via subscript causing a compilation error. The error manifested during the integration of the collection after long debugging.


Story

In a custom subscript, they did not implement proper handling for out-of-bounds access, which caused crashes when accessing out of range. As a result, business-critical data processing functions failed.


Story

They implemented a subscript with two parameters in an enum for caching, but did not consider that a subscript cannot be static (on the type) but only on the instance. The architectural decision turned out to be erroneous, and the API interaction of the collection had to be rewritten.