Latest web development tutorials

Swift automático de recuento de referencia (ARC)

Swift Uso de referencia automática Counting (ARC) este mecanismo para rastrear y administrar la memoria de aplicación

En circunstancias normales, no es necesario para liberar manualmente la memoria, debido a que el ARC será una instancia de la clase ya no se utiliza, de forma automática liberar memoria.

Pero todavía tenemos que implementar el código de gestión de memoria en algunos casos.

función ARC

  • Cuando init () Crea una nueva instancia de una clase de cada método cuando, ARC asignará un trozo de memoria para almacenar información de instancia.

  • El tipo de información contenida en la memoria se casos, así como el valor de esta instancia todos los atributos relevantes.

  • Cuando ya no se utiliza la instancia, ARC liberar la memoria ocupada por el ejemplo, y dejar que la memoria liberada se puede utilizar para otros fines.

  • Para asegurarse de que la instancia no será destruida, ARC hará un seguimiento y calcular cada caso está siendo referenciado por el número de atributos, constantes y variables.

  • Ejemplos asignados a la propiedad, constante o variable, que crearán una fuerte referencia este caso, siempre que la referencia sigue siendo fuerte, no se permite la instancia para ser destruidos.

ejemplos 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 salida por encima de la ejecución del programa es:

w3big 开始初始化
w3big 被析构

Ejemplos de fuerte circulación entre las referencias de clases

En el ejemplo anterior, ARC hará un seguimiento de su número de referencia Persona de nueva creación de instancias, y será destruida cuando la instancia de la persona ya no es necesaria.

Sin embargo, podríamos escribir código como este, nunca habrá una clase 0 referencias fuertes. Esto ocurre en dos instancias de clases para mantener las referencias fuertes el uno al otro, y dejar que la otra parte no será destruido. Se trata de los llamados fuertes referencias circulares.

Ejemplos

El siguiente ejemplo muestra un bucle producir inadvertidamente referencias fuertes. Ejemplo define dos clases: Persona y Apartamento, utilizados para modelar apartamento y sus habitantes fueron:

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

Los ejemplos de solución fuerte circula entre la referencia

Swift ofrece dos maneras de resolver el bucle se utiliza el atributo de clase cuando se encuentran las preguntas de referencia fuertes:

  • referencias débiles
  • No hay referencias primarias

referencias débiles y no hay referencias principales permiten una referencia circular en una instancia de una referencia a otra instancia sin mantener una fuerte referencia. Tales casos pueden referirse unos a otros sin generar un ciclo de referencia fuerte.

Para el ciclo de la vida se vuelve nula ejemplo utiliza referencias débiles. En contraste, después de los valores de inicialización no serán asignados a instancia nil, el uso de referencia no primaria.

Ejemplos de referencias débiles

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 salida por encima de la ejecución del programa es:

ARC 主模块
子模块 topic 数为 4

No hay ejemplos de referencia principales

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 salida por encima de la ejecución del programa es:

ARC
学生的分数为 98

cierres de lazo causadas por referencias fuertes

ciclo de referencia fuerte se produce cuando se asigna una instancia de clase de cierre de una propiedad, y el cuerpo de cierre y el uso de ejemplos. El cuerpo de cierre puede acceder a instancias de propiedad, como self.someProperty, o el cierre de unos métodos de instancia de llamada, tales self.someMethod. Ambos casos han conducido al cierre de "captura" sí, lo que resulta en un ciclo de referencias fuertes.

Ejemplos

¿Cómo después de ejemplo siguiente se muestra cuando un cierre es producir una referencia a las referencias fuertes bucle auto. Ejemplo define una clase llamada HTMLElement, expresado en un modelo simple de un solo 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())

HTMLElement clase produjo una clase de instancias y cierres de ciclo asHTML valores por defecto entre las referencias fuertes.

Fuerte ejemplo propiedad asHTML contiene una referencia a la clausura. Sin embargo, el cierre de su cierre el uso in vivo de sí mismo (citado self.name y self.text), y por lo tanto la captura de auto cierre, lo que significa el cierre, a su vez, tiene una fuerte referencia HTMLElement instancia. Así que los dos objetos produce referencia fuerte circular.

bucle de cierre provocado por la fuerte determinación Cita: Al definir un cierre al mismo tiempo como parte de la definición de la lista de cierre de la captura de esta manera se puede resolver entre los módulos de cierre y una fuerte referencia a la instancia de clase.


referencias débiles y referencias sin dueño

Cuando una instancia de cierres y capturado se refieren siempre a la otra y están siempre al mismo tiempo destruido, capturado dentro de la definición de cierre hay referencia principal.

A la inversa, cuando las referencias de captura puede a veces ser nulo, el cierre será capturado dentro de la definición de las referencias débiles.

Si se captura una referencia no se establecerá a cero, debe hacerse referencia principal en lugar de referencias débiles.

Ejemplos

HTMLElement ejemplo anterior, la referencia principal hay una forma correcta de resolver referencia fuerte circular. Tal clase de HTMLElement escritura para evitar la referencia circular fuerte:

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 salida por encima de la ejecución del programa es:

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