Latest web development tutorials

Swift automático de contagem de referência (ARC)

Swift Use Referência Automatic Counting (ARC) este mecanismo para controlar e gerenciar memória de aplicativo

Em circunstâncias normais, não precisamos de libertar manualmente a memória, porque o ARC será uma instância da classe não é mais usado, automaticamente liberar memória.

Mas ainda precisamos implementar o código de gerenciamento de memória em alguns casos.

função ARC

  • Quando init () Cria uma nova instância de uma classe de cada método quando, ARC irá alocar um bloco de memória para o armazenamento de instância informações.

  • O tipo das informações contidas na memória serão instâncias, bem como o valor do presente exemplo, todos os atributos relevantes.

  • Quando a instância não está sendo usada, ARC libertar a memória ocupado pelo exemplo, e deixar a memória libertada pode ser utilizada para outros fins.

  • Para garantir que a instância não será destruída, ARC irá rastrear e calcular cada instância está sendo referenciado pelo número de atributos, constantes e variáveis.

  • Exemplos atribuídos à propriedade, constante ou variável, que irão criar uma forte referência neste caso, enquanto a referência é ainda forte, o exemplo não é autorizado a ser destruída.

exemplos 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

A saída de execução de programa acima é:

w3big 开始初始化
w3big 被析构

Exemplos de forte circulação entre as referências de classe

No exemplo acima, ARC irá acompanhar o seu número de referência Pessoa recém-criado de instâncias, e ele será destruído quando a instância de Pessoa não é mais necessário.

No entanto, podemos escrever código como este, nunca haverá uma classe 0 referências fortes. Isso ocorre de duas instâncias de classe para manter as referências fortes para o outro, e deixar a outra parte não será destruída. Este é o chamado fortes referências circulares.

Exemplos

O exemplo a seguir mostra um ciclo inadvertidamente produzir referências fortes. Exemplo define duas classes: Pessoa e apartamento, usados ​​para modelar apartamento e seus habitantes foram:

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

Exemplos de solução forte circula entre a referência

Swift fornece duas maneiras de resolver o loop você usa o atributo da classe quando encontrados questões de referência fortes:

  • referências fracas
  • Não há referências primárias

referências fracas e sem principais referências permitem uma referência circular em uma instância de uma referência para outra instância sem manter uma referência forte. Nesses casos pode referir-se uns aos outros sem gerar um ciclo de referência forte.

Para o ciclo de vida torna-se exemplo nil usa referências fracas. Em contraste, após os valores de inicialização não irá ser atribuído ao exemplo nulo, o uso de referência não primário.

Exemplos de referências fracas

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

A saída de execução de programa acima é:

ARC 主模块
子模块 topic 数为 4

Não há exemplos de referência principais

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

A saída de execução de programa acima é:

ARC
学生的分数为 98

fechamentos de laço causadas por fortes referências

ciclo de referência forte também ocorre quando você atribui um fecho de instância de classe de uma propriedade, eo corpo de fecho e o uso de exemplos. O corpo de fecho pode acessar um instâncias de propriedade, tais como self.someProperty, ou o encerramento de uma chamada de métodos de instância, tais self.someMethod. Ambos os casos levaram ao fechamento "captura" auto, resultando num ciclo de referências fortes.

Exemplos

Como depois de seguir exemplo mostra quando um fechamento é produzir uma referência às referências auto de loop fortes. Exemplo define uma classe chamada HTMLElement, expressa em um modelo simples de um único 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 produziu instâncias de classe de ciclo e fechamentos asHTML valores padrão entre as referências fortes.

Strong asHTML instância propriedade contém uma referência para o encerramento. No entanto, o encerramento de seu fechamento em uso vivo da auto (citado self.name e self.text), e, portanto, o auto de captura de fechamento, o que significa o fechamento, por sua vez, contém uma referência forte HTMLElement instância. Assim que os dois objetos produz forte referência circular.

fechamento de loop causada pela forte Citar determinação: Quando você define um fecho ao mesmo tempo como parte da definição do encerramento lista de capturas desta forma possa ser resolvida entre os encerramentos loop e uma forte referência para a instância da classe.


referências fracas e referências sem dono

Quando uma instância de encerramentos e capturou sempre se referem uns aos outros e são sempre ao mesmo tempo destruída, capturada na definição de fechamento há referência principal.

Por outro lado, quando as referências de captura podem, por vezes, ser nulo, o fecho será capturado dentro da definição de referências fracas.

Se você capturar uma referência não será definido como nulo, ele não deve ser principal referência em vez de referências fracas.

Exemplos

HTMLElement precede exemplo, a referência principal é nenhuma maneira direita de resolver forte referência circular. Essa classe de escrita HTMLElement para evitar forte referência circular:

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

A saída de execução de programa acima é:

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