ProgrammationDéveloppeur iOS

Expliquez les différences entre les types de valeur et les types de référence en Swift. Quand faut-il utiliser chacun d'eux ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

En Swift, il existe deux types de données principaux : value types (types de valeur) et reference types (types de référence).

  • Types de valeur. Cela inclut les structures (struct), les énumérations (enum) et les types de base comme Int, Double, Bool. Lors de la transmission ou de l'affectation, la valeur est copiée, c'est-à-dire que les modifications de la copie n'affectent pas l'original.
  • Types de référence. Ce sont les classes (class) et les types associés. Lors de la transmission, ce n'est pas l'objet lui-même qui est copié, mais une référence à celui-ci, donc les modifications via une référence sont visibles via d'autres.

Quand utiliser :

  • Utilisez les types de valeur si vous souhaitez que les données soient des copies indépendantes (par exemple, CGPoint, CGSize, des modèles qui ne doivent pas partager d'état).
  • Les types de référence conviennent si un partage d'état entre les objets est requis (par exemple, les gestionnaires, les contrôleurs, les services).

Exemple :

struct Point { var x: Int var y: Int } class Person { var name: String init(name: String) { self.name = name } } var p1 = Point(x: 0, y: 0) var p2 = p1 p2.x = 10 // p1.x restera égal à 0 var person1 = Person(name: "Alex") var person2 = person1 person2.name = "Sam" // person1.name sera également "Sam"

Question piège.

Quelle est la différence entre let pour struct et class ? Un objet class créé avec let est-il complètement immuable ?

Réponse :

Pour les types de valeur (struct), let rend l'objet et ses propriétés immuables.

Pour les types de référence (class), let empêche la réaffectation de la référence, mais ne protège pas les propriétés de l'objet. Elles peuvent être modifiées si elles ne sont pas déclarées comme let à l'intérieur de la classe.

Exemple :

class Box { var value: Int init(value: Int) { self.value = value } } let box = Box(value: 10) box.value = 20 // OK! // box = Box(value: 30) // Erreur : impossibilité de réaffecter box

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


Histoire

Dans une application de paiement, le modèle de transaction était défini comme une classe, bien qu'il ne devrait pas y avoir d'état. Il y a eu un bug : lors du travail simultané avec une liste de transactions, il y avait une modification imprévisible des données de différentes parties de l'interface. Il a été décidé de convertir les modèles en struct pour que chaque composant travaille avec sa propre copie.


Histoire

Dans un projet, les paramètres utilisateur étaient stockés dans une classe, pensant que les valeurs étaient copiées lors de la transmission. Lors de la modification des données, un écran influençait involontairement un autre, car les deux travaillaient avec la même référence à l'objet.


Histoire

Dans le module de sérialisation, les données du modèle étaient déclarées comme un type de référence, ce qui entraînait des modifications entraînant des corruptions d'état dans le cache. Après être passé aux types de valeur, le problème a disparu : les données sont devenues indépendantes à chaque opération.