Swift - przegląd ARC
Funkcje zarządzania pamięcią i jej użycie są obsługiwane w języku Swift 4 poprzez automatyczne liczenie referencji (ARC). ARC służy do inicjowania i deinicjalizacji zasobów systemowych, zwalniając tym samym przestrzenie pamięci używane przez instancje klas, gdy instancje nie są już potrzebne. ARC śledzi informacje o relacjach między naszymi instancjami kodu, aby efektywnie zarządzać zasobami pamięci.
Funkcje ARC
ARC przydziela porcję pamięci do przechowywania informacji za każdym razem, gdy nowa instancja klasy jest tworzona przez init ().
Informacje o typie instancji i jej wartościach są przechowywane w pamięci.
Gdy instancja klasy nie jest już potrzebna, automatycznie zwalnia przestrzeń pamięci przez deinit () w celu dalszego przechowywania i pobierania instancji klasy.
ARC śledzi aktualnie odwołujące się właściwości instancji klas, stałe i zmienne, dzięki czemu funkcja deinit () jest stosowana tylko do tych nieużywanych instancji.
ARC utrzymuje „silne odniesienie” do tych właściwości instancji klasy, stałych i zmiennych, aby ograniczyć cofanie alokacji, gdy instancja klasy jest aktualnie używana.
Program 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)
Gdy uruchomimy powyższy program za pomocą placu zabaw, otrzymamy następujący wynik -
Swift 4
98
ARC Strong Reference Cycles Class Instances
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
Gdy uruchomimy powyższy program za pomocą placu zabaw, otrzymamy następujący wynik -
Initializing: Swift 4
Initializing: ARC
Słabe i nieznane referencje ARC
Właściwości typu klasy mają dwa sposoby rozwiązywania silnych cykli odwołań -
- Słabe odniesienia
- Nieznane referencje
Te odwołania są używane, aby umożliwić jednej instancji odwoływanie się do innych instancji w cyklu referencyjnym. Wtedy instancje mogą odnosić się do każdego wystąpienia, zamiast dbać o silny cykl odniesienia. Gdy użytkownik wie, że jakaś instancja może zwrócić wartości „nil”, możemy wskazać na to, używając słabego odwołania. Kiedy instancja zwróci coś, a nie zero, zadeklaruj to z odwołaniem, którego nie jesteś właścicielem.
Słaby program referencyjny
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
Gdy uruchomimy powyższy program za pomocą placu zabaw, otrzymamy następujący wynik -
ARC Is The Main Module
Sub Module with its topic number is 4
Nieznany program referencyjny
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
Gdy uruchomimy powyższy program za pomocą placu zabaw, otrzymamy następujący wynik -
ARC
Marks Obtained by the student is 98
Silne cykle referencyjne dla zamknięć
Kiedy przypiszemy zamknięcie do właściwości instancji klasy i do treści zamknięcia w celu przechwycenia określonej instancji, może wystąpić silny cykl odniesienia. Silne odniesienie do zamknięcia jest definiowane przez „self.someProperty” lub „self.someMethod ()”. Silne cykle referencyjne są używane jako typy referencyjne dla zamknięć.
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())
Gdy uruchomimy powyższy program za pomocą placu zabaw, otrzymamy następujący wynik -
<p>Welcome to Closure SRC</p>
Słabe i nieznane referencje
Gdy zamknięcie i wystąpienie odnoszą się do siebie nawzajem, użytkownik może zdefiniować wychwycenie w zamknięciu jako odniesienie nieposiadane. Wtedy nie pozwoliłoby użytkownikowi na jednoczesne zwolnienie instancji. Kiedy instancja kiedyś zwróci wartość „zero”, zdefiniuj zamknięcie słabą instancją.
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
Gdy uruchomimy powyższy program za pomocą placu zabaw, otrzymamy następujący wynik -
<Inside>ARC Weak References</Inside>
Inside the deinit()