Latest web development tutorials

Swift automatico di conteggio di riferimento (ARC)

Swift Usa Riferimento conteggio automatico (ARC) questo meccanismo per monitorare e gestire la memoria di applicazione

In circostanze normali, non abbiamo bisogno di liberare manualmente la memoria, perché l'ARC sarà un'istanza della classe non è più utilizzato, automaticamente liberare memoria.

Ma abbiamo ancora bisogno di implementare il codice di gestione della memoria in alcuni casi.

funzione ARC

  • Quando init () Crea una nuova istanza di una classe di ciascun metodo quando, ARC allocherà un pezzo di memoria per memorizzare informazioni esempio.

  • Il tipo di informazioni contenute nella memoria sarà istanze, così come il valore di questa istanza tutti gli attributi rilevanti.

  • Se non viene più utilizzata l'istanza, ARC rilascia la memoria occupata dal caso, e lasciare che la memoria liberata può essere utilizzato per altri scopi.

  • Per garantire che l'istanza non sarà distrutta, ARC terrà traccia e calcolare ogni istanza è fatto riferimento per il numero di attributi, costanti e variabili.

  • Esempi assegnati alla proprietà, costante o variabile, creeranno un forte riferimento fattispecie, purché il riferimento è ancora forte, l'istanza non può essere distrutto.

Esempi di ARC

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

L'output sopra l'esecuzione del programma è il seguente:

w3big 开始初始化
w3big 被析构

Esempi di forte circolazione tra i riferimenti di classe

Nell'esempio precedente, ARC sarà monitorare il numero di riferimento Persona di recente creazione di istanze, e sarà distrutto quando non è più necessaria l'istanza di Person.

Tuttavia, potremmo scrivere codice in questo modo, non ci sarà mai una classe 0 riferimenti forti. Ciò si verifica in due istanze di classe per mantenere i riferimenti forti tra di loro, e lasciare che l'altra parte non sarà distrutta. Questo è il cosiddetto forti riferimenti circolari.

Esempi

L'esempio seguente mostra un loop inavvertitamente produrre riferimenti forti. Esempio definisce due classi: Persona e appartamento, utilizzati per modellare appartamento ei suoi abitanti sono stati:

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

Esempi di forte soluzione circola tra il riferimento

Swift offre due modi per risolvere il loop si utilizza l'attributo di classe quando incontra domande di riferimento forti:

  • riferimenti deboli
  • Non ci sono riferimenti primari

riferimenti deboli e senza riferimenti principali consentono un riferimento circolare in un'istanza di un riferimento a un'altra istanza senza mantenere un riferimento forte. Questi casi possono riferimento l'uno all'altro senza generare un ciclo di riferimento forte.

Per il ciclo di vita diventa nullo esempio utilizza riferimenti deboli. Al contrario, dopo non verranno assegnati i valori di inizializzazione per esempio nullo, l'uso di riferimento non primario.

Esempi di riferimenti deboli

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

L'output sopra l'esecuzione del programma è il seguente:

ARC 主模块
子模块 topic 数为 4

Non ci sono esempi principali di riferimento

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

L'output sopra l'esecuzione del programma è il seguente:

ARC
学生的分数为 98

chiusure Loop causate da forti riferimenti

ciclo di riferimento forte si verifica anche quando si assegna una chiusura istanza della classe di un immobile, e il corpo di chiusura e l'uso di esempi. Il corpo di chiusura può accedere ad una le istanze di proprietà, come self.someProperty, o la chiusura di una chiamata di metodi di istanza, come self.someMethod. Entrambi i casi hanno portato alla chiusura "cattura" auto, causando un ciclo di riferimenti forti.

Esempi

Come dopo esempio seguente mostra quando una chiusura è quello di produrre un riferimento alle auto ciclo riferimenti forti. Esempio definisce una classe chiamata HTMLElement, espresso in un semplice modello di un singolo elemento HTML:

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())

Classe HTMLElement prodotto un ciclo di istanze di classe e chiusure asHTML valori di default tra i riferimenti forti.

Forte esempio proprietà asHTML contiene un riferimento alla chiusura. Tuttavia, la chiusura della sua chiusura in uso vivo di sé (cit self.name e self.text), e quindi l'angolo di cattura di chiusura, cioè la chiusura, a sua volta, contiene un riferimento forte HTMLElement esempio. In modo che i due oggetti produce riferimento circolare forte.

Chiusura del ciclo causato dalla forte determinazione Citazione: Quando si definisce una chiusura allo stesso tempo come parte della definizione della chiusura lista catture in questo modo può essere risolta tra le chiusure loop e un riferimento forte per l'istanza della classe.


riferimenti deboli e riferimenti senza padrone

Quando un'istanza di chiusure e catturato sempre riferimento l'uno all'altro e sono sempre contemporaneamente distrutta, catturato nella definizione di chiusura è alcun riferimento principale.

Viceversa, quando i riferimenti di cattura possono talvolta essere pari a zero, la chiusura sarà catturata nella definizione di riferimenti deboli.

Se si cattura un riferimento non sarà impostato a zero, dovrebbe essere nessun riferimento principale invece di riferimenti deboli.

Esempi

HTMLElement rinunciare esempio, il riferimento principale è un modo giusto per risolvere riferimento circolare forte. Tale classe HTMLElement scrittura per evitare di riferimento circolare forte:

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

L'output sopra l'esecuzione del programma è il seguente:

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