Kā darbojas automātiskās atmiņas pārvaldības (ARC) mehānisms Swift valodā?
sobes.tech AI
Atbilde no AI
ARC (Automātiskā atsauču skaitīšana) automātiski uzrauga un pārvalda atsauces uz klases piemēriem. Tas atbrīvo atmiņu, ko aizņem piemērs, kad uz to vairs nav stipru atsauču. ARC darbojas tikai ar klases piemēriem, nevis ar struktūrām vai enumerācijām, jo tie ir vērtību tipi.
Trīs veidu saites starp piemēriem:
- Strong (Spēcīga): Saite, kas palielina atsauču skaitītāju piemēram. Noklusējuma visām saitēm ir stipras.
- Weak (Vāja): Saite, kas nesasniedz atsauču skaitītāju. Izmanto, lai novērstu stipro saišu ciklus.
weaktipa saites vienmēr ir opcijas, jo piemērs var tikt atbrīvots jebkurā brīdī. - Unowned (Nepiederīgs): Saite, kas nesasniedz atsauču skaitītāju un tiek izmantota, kad garantēts, ka saistītais piemērs pastāvēs ilgāk nekā pašreizējais. Nav obligāta, bet, mēģinot piekļūt atbrīvotam piemēram, rodas izpildes kļūda.
Stipro saišu cikli rodas, kad divi vai vairāk piemēru ir stipras saites viens uz otru, novēršot to atbrīvošanu ARC. Šos ciklus risina, izmantojot weak vai unowned saites.
Stipru saišu cikla piemērs:
class Person {
let name: String
var apartment: Apartment?
init(name: String) {
self.name = name
}
deinit { // izbeigšanas laikā
print("\(name) tiek atbrīvots")
}
}
class Apartment {
let unit: String
var tenant: Person?
init(unit: String) {
self.unit = unit
}
deinit { // izbeigšanas laikā
print("Dzīvoklis \(unit) tiek atbrīvots")
}
}
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 // Nekas netiek izvadīts, jo ir cikls
Risinājums stipru saišu ciklam ar weak:
class Person {
let name: String
var apartment: Apartment?
init(name: String) {
self.name = name
}
deinit {
print("\(name) tiek atbrīvots")
}
}
class Apartment {
let unit: String
weak var tenant: Person? // Vāja saite uz Person
init(unit: String) {
self.unit = unit
}
deinit {
print("Dzīvoklis \(unit) tiek atbrīvots")
}
}
var john: Person?
var unit4A: Apartment?
john = Person(name: "John Appleseed")
unit4A = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john
john = nil // Atbrīvo Person
unit4A = nil // Atbrīvo Apartment
Risinājums stipru saišu ciklam ar unowned:
class Customer {
let name: String
var card: CreditCard?
init(name: String) {
self.name = name
}
deinit {
print("\(name) tiek atbrīvots")
}
}
class CreditCard {
let number: UInt64
unowned let customer: Customer // Nepiederīgs saite uz Customer
init(number: UInt64, customer: Customer) {
self.number = number
self.customer = customer
}
deinit {
print("Karte #\(number) tiek atbrīvota")
}
}
var john: Customer?
john = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
john = nil // Atbrīvo Customer un CreditCard
ARC un slēdzenes: Slēdzenes arī var radīt ciklus, aizskarot klases piemērus. Lai to novērstu, tiek izmantoti [weak self] vai [unowned self]:
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = { // lazy, lai izmantotu self pirms inicializācijas
[unowned self] in // aizskaršanas saraksts
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) tiek atbrīvots")
}
}
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "sveiki, pasaule")
print(paragraph!.asHTML())
paragraph = nil // Atbrīvo HTMLElement