Latest web development tutorials

Swift référence Comptage automatique (ARC)

Swift utilisation de référence automatique de comptage (ARC) ce mécanisme pour suivre et gérer la mémoire d'application

Dans des circonstances normales, on n'a pas besoin de libérer manuellement la mémoire, parce que l'ARC sera une instance de la classe est plus utilisé, automatiquement libérer de la mémoire.

Mais nous avons encore besoin de mettre en œuvre le code de gestion de la mémoire dans certains cas.

fonction ARC

  • Lorsque init () Crée une nouvelle instance d'une classe de chaque méthode lorsque, ARC allouera un morceau de mémoire pour stocker par exemple de l'information.

  • Le type d'informations contenues dans la mémoire sera instances, ainsi que la valeur de cette instance tous les attributs pertinents.

  • Lorsque l'instance est plus utilisé, ARC libérer la mémoire occupée par l'instance, et que la mémoire libérée peut être utilisée à d'autres fins.

  • Pour veiller à ce que l'instance ne sera pas détruit, ARC permettra de suivre et calculer chaque instance est référencé par le nombre d'attributs, des constantes et des variables.

  • Exemples affectés à la propriété, constante ou variable, ils vont créer une référence forte ce cas, aussi longtemps que la référence est encore forte, l'instance ne peut pas être détruit.

Exemples d'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

La sortie de l'exécution du programme ci-dessus est la suivante:

w3big 开始初始化
w3big 被析构

Des exemples de forte circulation entre les références de classe

Dans l'exemple ci-dessus, l'ARC permettra de suivre votre numéro de référence Personne nouvellement créé de cas, et il sera détruit lorsque l'instance Personne ne sont plus nécessaires.

Cependant, nous pourrions écrire du code comme ça, il n'y aura jamais une classe 0 références solides. Cela se produit dans deux instances de classe pour maintenir de solides références à l'autre, et de laisser l'autre partie ne sera pas détruit. Ce sont les soi-disant solides références circulaires.

Exemples

L'exemple suivant montre une boucle de produire, par inadvertance, de solides références. Exemple définit deux classes: Personne et Appartement, utilisées pour modéliser l'appartement et ses habitants étaient les suivants:

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

Des exemples de solution solide circule entre la référence

Swift fournit deux façons de résoudre la boucle que vous utilisez l'attribut de classe lorsque rencontré des questions de référence fortes:

  • références faibles
  • Pas de références primaires

références faibles et pas de références principales permettent une référence circulaire dans une instance d'une référence à une autre instance sans maintenir une référence forte. Ces instances peuvent se référer les uns aux autres sans générer un cycle de référence forte.

Pour le cycle de vie devient nulle instance utilise des références faibles. En revanche, après les valeurs d'initialisation ne seront pas affectés à l'instance nulle, l'utilisation de référence non-primaire.

Des exemples de références faibles

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

La sortie de l'exécution du programme ci-dessus est la suivante:

ARC 主模块
子模块 topic 数为 4

Aucun des principaux exemples de référence

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

La sortie de l'exécution du programme ci-dessus est la suivante:

ARC
学生的分数为 98

fermetures de boucle causées par des références fortes

cycle de référence fort se produit également lorsque vous affectez une fermeture d'instance de classe d'une propriété, et le corps de fermeture et l'utilisation d'exemples. Le corps de fermeture peut accéder à un cas de propriété, comme self.someProperty, ou la fermeture d'un appel des méthodes d'instance, comme self.someMethod. Les deux cas ont conduit à la fermeture "capture" self, ce qui entraîne un cycle de solides références.

Exemples

Comment après l'exemple suivant vous montre quand la fermeture est de produire une référence aux auto boucle de solides références. Exemple définit une classe appelée HTMLElement, exprimée dans un modèle simple d'un élément HTML simple:

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 a produit un cas et les fermetures de classes du cycle asHTML valeurs par défaut entre des références fortes.

Forte instance de propriété asHTML contient une référence à la fermeture. Cependant, la fermeture de sa fermeture en utilisation in vivo de l'auto (cité self.name et self.text), et donc l'auto fermeture de capture, ce qui signifie la fermeture, à son tour, détient une référence forte HTMLElement instance. Alors que les deux objets produit référence circulaire forte.

la fermeture de la boucle provoquée par la citation de forte détermination: Lorsque vous définissez une fermeture en même temps, dans le cadre de la définition de la liste des prises de fermeture de cette manière peut être résolu entre les fermetures de boucles et une forte référence à l'instance de classe.


références et références ownerless faibles

Lorsqu'une instance de fermetures et capturé se réfèrent toujours à l'autre et sont toujours en même temps détruit, capturé dans la définition de fermeture est fait aucune référence principale.

A l'inverse, lorsque les références de capture peuvent parfois être nuls, la fermeture sera capturé dans la définition des références faibles.

Si vous capturez une référence ne sera pas mis à zéro, il ne devrait pas être la référence principale au lieu de références faibles.

Exemples

HTMLElement exemple précédent, la principale référence est pas de bonne façon de résoudre référence circulaire forte. Cette classe d'écriture HTMLElement pour éviter référence circulaire 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

La sortie de l'exécution du programme ci-dessus est la suivante:

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