Swift - Descripción general de ARC

Las funciones de administración de memoria y su uso se manejan en el idioma Swift 4 a través del conteo automático de referencias (ARC). ARC se usa para inicializar y desinicializar los recursos del sistema, liberando así los espacios de memoria usados ​​por las instancias de clase cuando las instancias ya no son necesarias. ARC realiza un seguimiento de la información sobre las relaciones entre nuestras instancias de código para administrar los recursos de memoria de manera efectiva.

Funciones de ARC

  • ARC asigna una parte de la memoria para almacenar la información cada vez que init () crea una nueva instancia de clase.

  • La información sobre el tipo de instancia y sus valores se almacena en la memoria.

  • Cuando la instancia de clase ya no es necesaria, automáticamente libera el espacio de memoria mediante deinit () para un mayor almacenamiento y recuperación de la instancia de clase.

  • ARC realiza un seguimiento de las propiedades, constantes y variables de las instancias de clase que se refieren actualmente, de modo que deinit () se aplica solo a las instancias no utilizadas.

  • ARC mantiene una 'fuerte referencia' a esas propiedades de instancia de clase, constantes y variables para restringir la desasignación cuando la instancia de clase está actualmente en uso.

Programa 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)

Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:

Swift 4
98

Instancias de clase 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

Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:

Initializing: Swift 4
Initializing: ARC

Referencias ARC débiles y sin dueño

Las propiedades de tipo de clase tienen dos formas de resolver fuertes ciclos de referencia:

  • Referencias débiles
  • Referencias sin propietario

Estas referencias se utilizan para permitir que una instancia haga referencia a otras instancias en un ciclo de referencia. Entonces, las instancias pueden referirse a todas y cada una de las instancias en lugar de preocuparse por un ciclo de referencia fuerte. Cuando el usuario sabe que alguna instancia puede devolver valores 'nulos', podemos señalar eso usando una referencia débil. Cuando la instancia va a devolver algo en lugar de nil, entonces declárelo con una referencia sin propietario.

Programa de referencia débil

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

Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:

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

Programa de referencia sin propietario

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

Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:

ARC
Marks Obtained by the student is 98

Ciclos de referencia fuertes para cierres

Cuando asignamos un cierre a la propiedad de instancia de clase y al cuerpo del cierre para capturar una instancia particular, puede ocurrir un ciclo de referencia fuerte. La fuerte referencia al cierre se define por 'self.someProperty' o 'self.someMethod ()'. Los ciclos de referencia fuertes se utilizan como tipos de referencia para los cierres.

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())

Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:

<p>Welcome to Closure SRC</p>

Referencias débiles y sin dueño

Cuando el cierre y la instancia se refieren entre sí, el usuario puede definir la captura en un cierre como una referencia sin dueño. Entonces no permitiría al usuario desasignar la instancia al mismo tiempo. Cuando la instancia en algún momento devuelva un valor 'nulo', defina el cierre con la instancia débil.

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

Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:

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