Swift - Présentation de l'ARC

Les fonctions de gestion de la mémoire et son utilisation sont gérées en langage Swift 4 via le comptage automatique des références (ARC). ARC est utilisé pour initialiser et désinitialiser les ressources système, libérant ainsi les espaces mémoire utilisés par les instances de classe lorsque les instances ne sont plus nécessaires. ARC garde une trace des informations sur les relations entre nos instances de code pour gérer efficacement les ressources mémoire.

Fonctions de l'ARC

  • ARC alloue un morceau de mémoire pour stocker les informations à chaque fois qu'une nouvelle instance de classe est créée par init ().

  • Les informations sur le type d'instance et ses valeurs sont stockées en mémoire.

  • Lorsque l'instance de classe n'est plus nécessaire, elle libère automatiquement l'espace mémoire par deinit () pour un stockage et une récupération supplémentaires de l'instance de classe.

  • ARC garde une trace des propriétés, des constantes et des variables des instances de classe faisant actuellement référence afin que deinit () ne soit appliqué qu'à ces instances non utilisées.

  • ARC maintient une «référence forte» à ces propriétés, constantes et variables d'instance de classe pour limiter la désallocation lorsque l'instance de classe est actuellement utilisée.

Programme ARC

class StudDetails {
   var stname: String!
   var mark: Int!
   
   init(stname: String, mark: Int) {
      self.stname = stname
      self.mark = mark
   }
   deinit {
      print("Deinitialized \(self.stname)")
      print("Deinitialized \(self.mark)")
   }
}

let stname = "Swift 4"
let mark = 98

print(stname)
print(mark)

Lorsque nous exécutons le programme ci-dessus en utilisant aire de jeux, nous obtenons le résultat suivant -

Swift 4
98

Instances de classe ARC Strong Reference Cycles

class studmarks {
   let name: String
   var stud: student?
   
   init (name: String) {
      print("Initializing: \(name)")
      self.name = name
   }
   deinit {
      print("Deallocating: \(self.name)")
   }
}

class student {
   let name: String
   var strname: studmarks?
   
   init (name: String) {
      print("Initializing: \(name)")
      self.name = name
   }
   deinit {
      print("Deallocating: \(self.name)")
   }
}

var shiba: studmarks?
var mari: student?

shiba = studmarks(name: "Swift 4")
mari = student(name: "ARC")

shiba!.stud = mari
mari!.strname = shiba

Lorsque nous exécutons le programme ci-dessus en utilisant aire de jeux, nous obtenons le résultat suivant -

Initializing: Swift 4
Initializing: ARC

ARC Références faibles et sans propriétaire

Les propriétés de type de classe ont deux façons de résoudre les cycles de référence forts -

  • Références faibles
  • Références non propriétaires

Ces références sont utilisées pour permettre à une instance de référencer d'autres instances dans un cycle de référence. Ensuite, les instances peuvent se référer à chaque instance au lieu de se soucier d'un cycle de référence fort. Lorsque l'utilisateur sait qu'une instance peut renvoyer des valeurs «nil», nous pouvons le signaler en utilisant une référence faible. Lorsque l'instance va renvoyer quelque chose plutôt que nil, déclarez-la avec une référence sans propriétaire.

Programme de référence faible

class module {
   let name: String
   init(name: String) { self.name = name }
   var sub: submodule?
   deinit { print("\(name) Is The Main Module") }
}

class submodule {
   let number: Int
   init(number: Int) { self.number = number }
   weak var topic: module?

   deinit { print("Sub Module with its topic number is \(number)") }
}

var toc: module?
var list: submodule?
toc = module(name: "ARC")
list = submodule(number: 4)
toc!.sub = list
list!.topic = toc

toc = nil
list = nil

Lorsque nous exécutons le programme ci-dessus en utilisant aire de jeux, nous obtenons le résultat suivant -

ARC Is The Main Module
Sub Module with its topic number is 4

Programme de référence sans propriétaire

class student {
   let name: String
   var section: marks?
   init(name: String) {
      self.name = name
   }
   deinit { print("\(name)") }
}

class marks {
   let marks: Int
   unowned let stname: student
   
   init(marks: Int, stname: student) {
      self.marks = marks
      self.stname = stname
   }
   deinit { print("Marks Obtained by the student is \(marks)") }
}

var module: student?
module = student(name: "ARC")
module!.section = marks(marks: 98, stname: module!)
module = nil

Lorsque nous exécutons le programme ci-dessus en utilisant aire de jeux, nous obtenons le résultat suivant -

ARC
Marks Obtained by the student is 98

Cycles de référence solides pour les fermetures

Lorsque nous affectons une fermeture à la propriété d'instance de classe et au corps de la fermeture pour capturer une instance particulière, un cycle de référence fort peut se produire. Une référence forte à la fermeture est définie par «self.someProperty» ou «self.someMethod ()». Des cycles de référence forts sont utilisés comme types de référence pour les fermetures.

class HTMLElement {
   let samplename: String
   let text: String?
   
   lazy var asHTML: () -> String = {
      if let text = self.text {
         return "<\(self.samplename)>\(text)</\(self.samplename)>"
      } else {
         return "<\(self.samplename) />"
      }
   }
   init(samplename: String, text: String? = nil) {
      self.samplename = samplename
      self.text = text
   }
   deinit {
      print("\(samplename) is being deinitialized")
   }
}

var paragraph: HTMLElement? = HTMLElement(samplename: "p", text: "Welcome to Closure SRC")
print(paragraph!.asHTML())

Lorsque nous exécutons le programme ci-dessus en utilisant aire de jeux, nous obtenons le résultat suivant -

<p>Welcome to Closure SRC</p>

Références faibles et inconnues

Lorsque la fermeture et l'instance se réfèrent l'une à l'autre, l'utilisateur peut définir la capture dans une fermeture comme une référence sans propriétaire. Ensuite, cela ne permettrait pas à l'utilisateur de désallouer l'instance en même temps. Lorsque l'instance retourne parfois une valeur «nil», définissez la fermeture avec l'instance faible.

class HTMLElement {
   let module: String
   let text: String?
   
   lazy var asHTML: () -> String = {
      [unowned self] in
      if let text = self.text {
         return "<\(self.module)>\(text)</\(self.module)>"
      } else {
         return "<\(self.module) />"
      }
   }
   init(module: String, text: String? = nil) {
      self.module = module
      self.text = text
   }
   deinit {
      print("\(module) the deinit()")
   }
}

var paragraph: HTMLElement? = HTMLElement(module: "Inside", text: "ARC Weak References")
print(paragraph!.asHTML())
paragraph = nil

Lorsque nous exécutons le programme ci-dessus en utilisant aire de jeux, nous obtenons le résultat suivant -

<Inside>ARC Weak References</Inside>
Inside the deinit()