Kuidas töötab automaatse mälu haldamise (ARC) mehhanism Swiftis?
sobes.tech AI
Vastus AI-lt
ARC (Automaatne viidete arvutamine) jälgib ja haldab automaatselt klasside näidete viiteid. See vabastab mälu, mida näide kasutab, kui sellele ei ole enam tugevaid viiteid. ARC töötab ainult klasside näidete puhul, mitte struktuuride või loendite puhul, kuna need on väärtustüübid.
Kolm tüüpi seoseid näidete vahel:
- Strong (Tugev): Seos, mis suurendab viidete loendurit näidetes. Vaikimisi on kõik viited tugevad.
- Weak (Nõrk): Seos, mis ei suurenda viidete loendurit. Kasutatakse tugevate tsüklite vältimiseks.
weaktüüpi viited on alati valikulised, kuna näide võib vabastada igal ajal. - Unowned (Omamata seos): Seos, mis ei suurenda viidete loendurit ja kasutatakse, kui on garanteeritud, et seotud näide eksisteerib kauem kui praegune. Ei ole kohustuslik, kuid proovimisel, kui pääseb ligi vabastatud näitele, tekib jooksu viga.
Tugevad tsüklid tekivad, kui kaks või enam näidet omavad üksteisele tugevaid viiteid, takistades nende vabastamist ARC-i abil. Nende tsüklite lahendamiseks kasutatakse weak või unowned viiteid.
Näide tugeva tsükli kohta:
class Person {
let name: String
var apartment: Apartment?
init(name: String) {
self.name = name
}
deinit { // vabastamise ajal
print("\(name) vabastatakse")
}
}
class Apartment {
let unit: String
var tenant: Person?
init(unit: String) {
self.unit = unit
}
deinit { // vabastamise ajal
print("Korter \(unit) vabastatakse")
}
}
var john: Person?
var unit4A: Apartment?
john = Person(name: "John Appleseed")
unit4A = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john
john = nil
unit4A = nil // Mitte midagi ei kuvata, kuna tekkinud tsükkel
Tugeva tsükli lahendamine weak kasutades:
class Person {
let name: String
var apartment: Apartment?
init(name: String) {
self.name = name
}
deinit {
print("\(name) vabastatakse")
}
}
class Apartment {
let unit: String
weak var tenant: Person? // Nõrk viide Person-ile
init(unit: String) {
self.unit = unit
}
deinit {
print("Korter \(unit) vabastatakse")
}
}
var john: Person?
var unit4A: Apartment?
john = Person(name: "John Appleseed")
unit4A = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john
john = nil // vabastab Person-i
unit4A = nil // vabastab Apartment-i
Tugeva tsükli lahendamine unowned kasutades:
class Customer {
let name: String
var card: CreditCard?
init(name: String) {
self.name = name
}
deinit {
print("\(name) vabastatakse")
}
}
class CreditCard {
let number: UInt64
unowned let customer: Customer // Omamata viide Customer-ile
init(number: UInt64, customer: Customer) {
self.number = number
self.customer = customer
}
deinit {
print("Kaart #\(number) vabastatakse")
}
}
var john: Customer?
john = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
john = nil // vabastab Customer ja CreditCard
ARC ja suletud funktsioonides: Suletud funktsioonid võivad samuti tekitada tsükleid, haarates klasside näiteid. Selle vältimiseks kasutatakse haaramisliste ([weak self] või [unowned self]):
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = { // lazy, et saaks kasutada self enne initsialiseerimist
[unowned self] in // haaramisloend
if let text = self.text {
return "<\(self.name)>\(text)</\(self.name)>"
} else {
return "<\(self.name) />"
}
}
init(name: String, text: String? = nil) {
self.name = name
self.text = text
}
deinit {
print("\(name) vabastatakse")
}
}
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "tere, maailm")
print(paragraph!.asHTML())
paragraph = nil // Vabastab HTMLElement