ProgrammationDéveloppeur iOS

Expliquez les caractéristiques du travail avec les Subscripts en Swift. Quelles sont les restrictions qui existent pour les subscripts, comment ce mécanisme peut-il être étendu et où doit-il être appliqué ? Donnez un exemple de subscript non standard.

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse

Subscripts en Swift permettent d'accéder aux valeurs d'un type par clé ou par indice, de manière similaire aux tableaux ou dictionnaires, mais pour n'importe quel type personnalisé. La syntaxe ressemble à celle d'une fonction, mais l'accès se fait entre crochets : object[key].

Caractéristiques :

  • Une classe ou une structure peut avoir plusieurs subscripts (surcharge par paramètres).
  • Un subscript peut être en lecture seule ou en lecture-écriture (contient uniquement get, ou get et set).
  • Un subscript peut avoir un nombre quelconque de paramètres et de types (par exemple, deux indices).
  • Pas de support pour les paramètres variadiques.

Application :

  • Pour un accès simplifié aux collections, matrices, objets personnalisés, valeurs sérialisables, etc.

Exemple : Un tableau à deux dimensions (matrice) et un subscript avec deux paramètres :

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

Question piège

Un subscript peut-il avoir un paramètre de type inout ou être mutating dans une structure ?

Réponse :

  • Le paramètre du subscript ne peut pas être inout.
  • Un subscript dans un type valeur (structure/énumération) peut être déclaré comme mutating set, ce qui permet de modifier self à l'intérieur de set :
struct Counter { var value: Int = 0 subscript(increment: Bool) -> Int { mutating get { value += increment ? 1 : -1 return value } } }

Exemples d'erreurs réelles dues à une méconnaissance des subtilités du sujet


Histoire

Dans une collection personnalisée, on a oublié de rendre le set dans le subscript mutating dans la structure, ce qui a entraîné que toute tentative de modifier un élément via le subscript générait une erreur de compilation. L'erreur s'est manifestée lors de l'intégration de la collection après un long débogage.


Histoire

Dans un subscript personnalisé, nous n'avons pas mis en place un traitement correct des débordements d'index, ce qui a causé des plantages lors des accès en dehors de la plage. Cela a entraîné des pannes de fonctions critiques pour l'entreprise de traitement des données.


Histoire

Un subscript avec deux paramètres a été réalisé pour un enum pour le caching, mais nous n'avons pas pris en compte que le subscript ne peut pas être static (au type), mais seulement sur une instance. La solution architecturale s'est avérée erronée, nous avons dû réécrire l'API d'interaction de la collection.