Swift - Panoramica ARC
Le funzioni di gestione della memoria e il suo utilizzo vengono gestiti nel linguaggio Swift 4 tramite il conteggio automatico dei riferimenti (ARC). ARC viene utilizzato per inizializzare e deinizializzare le risorse di sistema rilasciando così gli spazi di memoria utilizzati dalle istanze della classe quando le istanze non sono più necessarie. ARC tiene traccia delle informazioni sulle relazioni tra le nostre istanze di codice per gestire in modo efficace le risorse di memoria.
Funzioni di ARC
ARC alloca un pezzo di memoria per memorizzare le informazioni ogni volta che una nuova istanza di classe viene creata da init ().
Le informazioni sul tipo di istanza e sui relativi valori vengono archiviate in memoria.
Quando l'istanza della classe non è più necessaria, libera automaticamente lo spazio di memoria tramite deinit () per ulteriore archiviazione e recupero dell'istanza della classe.
ARC tiene traccia delle proprietà, delle costanti e delle variabili delle istanze di classe attualmente referenti in modo che deinit () venga applicato solo a quelle istanze inutilizzate.
ARC mantiene un "forte riferimento" a quelle proprietà, costanti e variabili dell'istanza di classe per limitare la deallocazione quando l'istanza di classe è attualmente in uso.
Programma 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)
Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:
Swift 4
98
Istanze di classe dei cicli di riferimento ARC Strong
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
Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:
Initializing: Swift 4
Initializing: ARC
Riferimenti ARC deboli e sconosciuti
Le proprietà del tipo di classe hanno due modi per risolvere i cicli di riferimento forti:
- Riferimenti deboli
- Riferimenti sconosciuti
Questi riferimenti vengono utilizzati per consentire a un'istanza di fare riferimento ad altre istanze in un ciclo di riferimento. Quindi le istanze possono fare riferimento a ciascuna di esse invece di preoccuparsi di un ciclo di riferimento forte. Quando l'utente sa che qualche istanza può restituire valori "nulli", possiamo indicarlo utilizzando un riferimento debole. Quando l'istanza restituirà qualcosa anziché zero, dichiararla con riferimento non proprietario.
Programma di riferimento debole
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
Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:
ARC Is The Main Module
Sub Module with its topic number is 4
Programma di riferimento sconosciuto
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
Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:
ARC
Marks Obtained by the student is 98
Forti cicli di riferimento per chiusure
Quando assegniamo una chiusura alla proprietà dell'istanza di classe e al corpo della chiusura per catturare un'istanza particolare, può verificarsi un forte ciclo di riferimento. Un forte riferimento alla chiusura è definito da 'self.someProperty' o 'self.someMethod ()'. I cicli di riferimento forti vengono utilizzati come tipi di riferimento per le chiusure.
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())
Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:
<p>Welcome to Closure SRC</p>
Riferimenti deboli e sconosciuti
Quando la chiusura e l'istanza si riferiscono l'una all'altra, l'utente può definire l'acquisizione in una chiusura come un riferimento non proprietario. Quindi non consentirebbe all'utente di deallocare l'istanza allo stesso tempo. Quando l'istanza a volte restituisce un valore 'nil', definire la chiusura con l'istanza debole.
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
Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:
<Inside>ARC Weak References</Inside>
Inside the deinit()