ProgrammationDéveloppeur iOS

Qu'est-ce que l'ARC en Swift ? Comment éviter un cycle de rétention lors de l'utilisation de closures et de délégués ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

ARC (Automatic Reference Counting) — système de gestion automatique de la mémoire en Swift. Chaque nouvelle référence forte à un objet augmente le compteur ; lors de la suppression, il diminue. Lorsque le compteur est à zéro, l'objet est libéré.

Cycle de rétention — situation où des objets se réfèrent mutuellement par des références fortes et ne sont jamais libérés.

Moyens d'éviter :

  • Pour les objets délégués, utilisez une référence faible :
protocol SomeDelegate: AnyObject { } class Owner { weak var delegate: SomeDelegate? }
  • Pour les closures, utilisez [weak self] ou [unowned self] :
class Example { var closure: (() -> Void)? func setup() { closure = { [weak self] in self?.doSomething() } } func doSomething() { } }

Question piège.

Quelle est la différence entre [weak self] et [unowned self] à l'intérieur d'une closure ? Quel type de référence utiliser et quand ?

Réponse :

  • [weak self] crée une référence optionnelle ; self peut être nil, donc on utilise généralement une extraction sécurisée self?.
  • [unowned self] crée une référence non-optionnelle et n'augmente PAS le compteur ; si l'objet est déjà libéré et qu'un accès se produit — cela provoquera un crash.
  • Le choix dépend de la logique métier : si la closure est garantie de vivre pas plus longtemps que self, vous pouvez utiliser [unowned self].

Exemple :

someClosure = { [weak self] in self?.doTask() } // ou (si self vit 100% plus longtemps que la closure) : someClosure = { [unowned self] in doTask() }

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


Histoire

Dans un projet, une situation de cycle de rétention s'est formée entre ViewController et sa closure, attachée à la gestion des pressions. ViewController se référencait à la closure, qui capturait self par une référence forte. En conséquence, le contrôleur et toutes ses données n'étaient pas libérés après la fermeture de l'écran. Le problème a été résolu en introduisant [weak self] dans la closure.


Histoire

Mise en œuvre du modèle delegate entre deux objets. Le delegate a été déclaré comme une propriété forte (strong). En conséquence, lors de la tentative de suppression de l'objet principal de la mémoire, il n'était pas désalloué, ce qui a conduit à une fuite de mémoire. Après avoir transféré le delegate sur weak, le problème a disparu.


Histoire

Pour une animation, une closure était utilisée à l'intérieur de UIView. La closure capturait self avec [unowned self]. Lorsque la vue était supprimée avant la fin de l'animation, l'application plantait en raison d'un accès à self déjà libéré. La solution — utilisation de [weak self] et vérification obligatoire que self n'est pas nil à l'intérieur de la closure.