Latest web development tutorials

Swift Automatische Referenzzählung (ARC)

Swift Verwenden Automatische Referenzzählung (ARC) dieser Mechanismus zu verfolgen und Applikationsspeicher verwalten

Unter normalen Umständen brauchen wir nicht manuell den Speicher freizugeben, weil die ARC eine Instanz der Klasse wird nicht mehr verwendet wird, automatisch Speicher freizugeben.

Aber wir brauchen noch Speicher-Management-Code in einigen Fällen zu implementieren.

ARC-Funktion

  • Wenn init () eine neue Instanz einer Klasse jeder Methode erstellt, wenn, wird ARC ein Stück Speicher zuweisen, um Informationen Instanz zu speichern.

  • Die Art der Informationen im Speicher enthaltenen Instanzen sowie der Wert dieser Instanz alle relevanten Attribute sein.

  • Wenn die Instanz nicht mehr verwendet wird, lassen Sie ARC die von der Instanz belegten Speicher, und lassen Sie können die freigegebenen Speicher für andere Zwecke verwendet werden.

  • Um sicherzustellen, dass die Instanz nicht zerstört werden, wird ARC verfolgen und zu berechnen, jeweils durch die Anzahl der Attribute, Konstanten und Variablen referenziert wird.

  • Beispiele zu der Eigenschaft zugewiesen, konstante oder variable, werden sie einen starken Bezug auf diese Instanz erstellen, solange die Referenz immer noch stark ist, wird die Instanz nicht zerstört werden darf.

ARC Beispiele

class Person {
    let name: String
    init(name: String) {
        self.name = name
        print("\(name) 开始初始化")
    }
    deinit {
        print("\(name) 被析构")
    }
}

// 值会被自动初始化为nil,目前还不会引用到Person类的实例
var reference1: Person?
var reference2: Person?
var reference3: Person?

// 创建Person类的新实例
reference1 = Person(name: "w3big")


//赋值给其他两个变量,该实例又会多出两个强引用
reference2 = reference1
reference3 = reference1

//断开第一个强引用
reference1 = nil
//断开第二个强引用
reference2 = nil
//断开第三个强引用,并调用析构函数
reference3 = nil

Die obige Programmausführung Ausgabe ist:

w3big 开始初始化
w3big 被析构

Beispiele für starke Zirkulation zwischen Klassenreferenzen

In dem obigen Beispiel wird ARC Ihre Spur neu erstellte Person Referenzanzahl von Instanzen, und es wird zerstört werden, wenn die Person beispielsweise nicht mehr benötigt wird.

Allerdings könnten wir Code wie diesen schreiben, es wird nie eine Klasse 0 starken Referenzen sein. Dies geschieht in zwei Klasseninstanzen starke Bezüge zueinander zu halten und lassen Sie die andere Partei nicht zerstört werden. Dies ist die so genannte starke zirkuläre Referenzen.

Beispiele

Das folgende Beispiel zeigt eine Schleife versehentlich starke Referenzen erzeugen. Beispiel definiert zwei Klassen: Person und Wohnung, verwendet Wohnung zu modellieren und ihre Bewohner waren:

class Person {
    let name: String
    init(name: String) { self.name = name }
    var apartment: Apartment?
    deinit { print("\(name) 被析构") }
}

class Apartment {
    let number: Int
    init(number: Int) { self.number = number }
    var tenant: Person?
    deinit { print("Apartment #\(number) 被析构") }
}

// 两个变量都被初始化为nil
var w3big: Person?
var number73: Apartment?

// 赋值
w3big = Person(name: "w3big")
number73 = Apartment(number: 73)

// 意感叹号是用来展开和访问可选变量 w3big 和 number73 中的实例
// 循环强引用被创建
w3big!.apartment = number73
number73!.tenant = w3big

// 断开 w3big 和 number73 变量所持有的强引用时,引用计数并不会降为 0,实例也不会被 ARC 销毁
// 注意,当你把这两个变量设为nil时,没有任何一个析构函数被调用。
// 强引用循环阻止了Person和Apartment类实例的销毁,并在你的应用程序中造成了内存泄漏
w3big = nil
number73 = nil

Beispiele für starke Lösung zirkuliert zwischen dem Referenz

Swift bietet zwei Möglichkeiten, um die Schleife Sie die Klasse-Attribut zu lösen, wenn eine starke Referenz Fragen auftreten:

  • Schwache Referenzen
  • Keine primäre Referenzen

Schwache Referenzen und keine Hauptreferenzen erlauben einen zirkulären Verweis in einer Instanz einer Referenz auf eine andere Instanz ohne einen starken Bezug zu halten. Solche Fälle miteinander ohne Erzeugung eines starken Referenzzyklus beziehen.

Für den gesamten Lebenszyklus wird null Beispiel schwache Verweise verwendet. Im Gegensatz dazu, nachdem die Initialisierungswerte werden nicht auf Null Instanz zugeordnet werden, die Verwendung von nicht-primären Referenz.

Beispiele für schwache Referenzen

class Module {
    let name: String
    init(name: String) { self.name = name }
    var sub: SubModule?
    deinit { print("\(name) 主模块") }
}

class SubModule {
    let number: Int
    
    init(number: Int) { self.number = number }
    
    weak var topic: Module?
    
    deinit { print("子模块 topic 数为 \(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

Die obige Programmausführung Ausgabe ist:

ARC 主模块
子模块 topic 数为 4

Keine Hauptreferenzbeispiele

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)") }
}

var module: Student?
module = Student(name: "ARC")
module!.section = Marks(marks: 98, stname: module!)
module = nil

Die obige Programmausführung Ausgabe ist:

ARC
学生的分数为 98

Loop-Verschlüsse, die durch starke Referenzen

Starke Referenzzyklus tritt auch auf, wenn Sie eine Instanz der Klasse Schließung einer Eigenschaft, und den Verschlusskörper und die Verwendung von Beispielen zuordnen. Der Verschlusskörper kann eine Eigenschaft Instanzen zugreifen, wie self.someProperty, oder die Schließung eines Call-Instanz-Methoden, wie self.someMethod. Beide Fälle haben closure "capture" self geführt, in einem Zyklus von starken Referenzen resultieren.

Beispiele

Wie nach dem Beispiel folgende zeigt Ihnen, wenn ein Verschluss ist ein Hinweis auf die Selbstschleife starken Referenzen zu erzeugen. Beispiel definiert eine Klasse Htmlelement, ausgedrückt in einem einfachen Modell eines einzelnen HTML-Element genannt:

class HTMLElement {
    
    let name: String
    let text: String?
    
    lazy var asHTML: () -> String = {
        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) is being deinitialized")
    }
    
}

// 创建实例并打印信息
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
print(paragraph!.asHTML())

Htmlelement-Klasse erzeugt ein Zyklus Klasseninstanzen und Schließungen asHTML Standardwerte zwischen starken Referenzen.

Starke asHTML Eigenschaft Instanz enthält einen Verweis auf den Verschluss. Allerdings ist die Schließung seiner Schließung in-vivo-Verwendung von Selbst (zitiert self.name und self.text) und damit die Schließung Erfassung selbst, der die Verschlussmittel, die wiederum hält eine starke Referenz Htmlelement-Instanz. Damit die beiden Objekte kreisförmig starke Referenz erzeugt.

Schleifenschluss verursacht durch die starke Entschlossenheit Zitat: Wenn Sie eine Schließung zur gleichen Zeit im Rahmen der Definition der Fangliste Schließung auf diese Weise definieren kann zwischen den Loop-Schließungen und einem starken Bezug auf die Klasseninstanz aufgelöst werden.


Schwache Verweise und Referenzen herrenlos

Wenn eine Instanz von Schließungen und immer aufeinander bezogen sind gefangen und sind immer in der gleichen Zeit zerstört, gefangen in der Definition der Schließung keine Haupt Referenz.

Wenn umgekehrt die Erfassungs Referenzen manchmal Null sein kann, wird der Verschluss in der Definition von schwache Verweise aufgenommen werden.

Wenn Sie eine Referenz erfassen wird nicht auf Null gesetzt werden, sollte es kein Hauptreferenz anstelle schwache Verweise sein.

Beispiele

Htmlelement Beispiel vorstehenden Ausführungen ist die Hauptbezugs keinen richtigen Weg kreisförmig starken Bezug zu lösen. Solche Schreibhtmlelement Klasse Kreis starken Bezug zu vermeiden:

class HTMLElement {
    
    let name: String
    let text: String?
    
    lazy var asHTML: () -> String = {
        [unowned self] in
        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) 被析构")
    }
    
}

//创建并打印HTMLElement实例
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
print(paragraph!.asHTML())

// HTMLElement实例将会被销毁,并能看到它的析构函数打印出的消息
paragraph = nil

Die obige Programmausführung Ausgabe ist:

<p>hello, world</p>
p 被析构