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