Middle
Pastāstiet mums par atmiņas pārvaldību iOS.
sobes.tech AI
Atbilde no AI
iOS izmanto automātisku atmiņas pārvaldību, izmantojot ARC (Automatic Reference Counting). ARC automātiski atbrīvo objektus, kad tiem vairs nav atsauces:
Galvenās koncepcijas:
- Stipra atsauce: Palielina atsauces skaitītāju uz objektu. Objekts netiks atbrīvots, kamēr ir stipras atsauces.
- Vāja atsauce: Nepalielina atsauces skaitītāju. Izmanto, lai novērstu stipro atsauču ciklus. Atsauce uz objektu, kas var tikt atbrīvots. Ja objekts tiek atbrīvots, vāja atsauce kļūst par
nil. - Nepārtraukta atsauce: Līdzīga vājai, bet neparādās
nilobjekta atbrīvošanas brīdī. Izmanto, ja objekts vienmēr ir pieejams vai tam ir ilgāks dzīves cikls. Nepārtraukta atsauce neparādāsnilatbrīvojot objektu. Mēģinot piekļūt atbrīvotam objektam caur nepārtrauktu atsauci, rodas izņēmums.
Stipro atsauču cikli (Retain Cycles): rodas, kad divi vai vairāki objekti ir stipri saistīti viens ar otru, neļaujot tiem tikt atbrīvotiem. To risina ar vājām vai nepārtrauktām atsaucēm.
Piemērs:
class Person {
let name: String
var apartment: Apartment?
init(name: String) {
self.name = name
print("\(name) sāk darboties")
}
deinit {
print("\(name) beidz darboties")
}
}
class Apartment {
let unit: String
weak var tenant: Person? // Vāja atsauce, lai novērstu ciklu
init(unit: String) {
self.unit = unit
print("Apartments \(unit) sāk darboties")
}
deinit {
print("Apartments \(unit) beidz darboties")
}
}
var john: Person? = Person(name: "John Appleseed")
var unit4A: Apartment? = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john // Šeit rodas cikls
john = nil
unit4A = nil
// Deinitializācijas metodes netiek izsauktas cikla dēļ
Risinājums ar weak:
class Person {
let name: String
var apartment: Apartment?
init(name: String) {
self.name = name
print("\(name) sāk darboties")
}
deinit {
print("\(name) beidz darboties")
}
}
class Apartment {
let unit: String
weak var tenant: Person? // Vāja atsauce, lai novērstu ciklu
init(unit: String) {
self.unit = unit
print("Apartments \(unit) sāk darboties")
}
deinit {
print("Apartments \(unit) beidz darboties")
}
}
var john: Person? = Person(name: "John Appleseed")
var unit4A: Apartment? = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john
john = nil
unit4A = nil
// Abi objekti tiek pareizi atbrīvoti
Nepārtraukta vs Vāja:
- Izmanto
weak, ja atsauce var kļūt parnil(objekts var tikt atbrīvots pirmais) - Izmanto
unowned, ja atsauce vienmēr būs ar vērtību (objekts, uz kuru atsaucas, ir ar tādu pašu vai ilgāku dzīves ciklu)
Aizvērumi (Closures) un cikli:
Aizvērumi var iekļaut objektu atsauces, radot stiprus ciklus. To risina ar capture list.
Piemērs:
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = {
[weak self] in // Ņemot `self` vājo atsauci
guard let self = self else {
return ""
}
var html = "<\(self.name)"
if let text = self.text {
html += ">\(text)</\(self.name)>"
} else {
html += " />"
}
return html
}
init(name: String, text: String? = nil) {
self.name = name
self.text = text
}
deinit {
print("\(name) beidz darboties")
}
}
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "sveiki, pasaule")
print(paragraph!.asHTML())
paragraph = nil
// Objekts ir atbrīvots
Atmiņas problēmu labošana:
- Memory Graph Debugger: Xcode ļauj vizualizēt objektu saites un identificēt ciklus
- Instruments (Allocations, Leaks): Uzrauga atmiņas sadali un atbrīvošanu, meklē zaudējumus.