Sobes.tech
Middle

Qual é a diferença entre links Wick e links Anound?

sobes.tech IA

Resposta da IA

A referência fraca (weak) é uma referência que não possui o controle do contador de referências do objeto. É usada para evitar ciclos de referências fortes, por exemplo, entre um delegado e seu proprietário. Se o objeto apontado pela referência fraca for desalocado, a referência fraca torna-se automaticamente nil.

A referência não possuída (unowned) também é uma referência que não aumenta o contador de referências do objeto. A diferença com weak é que unowned não pode ser opcional (Optional) e deve sempre apontar para um objeto existente. Se o objeto apontado pela referência unowned for desalocado antes que a referência deixe de existir, uma tentativa de acesso a essa referência resultará em um erro de execução (erro fatal). É usada onde o ciclo de vida do objeto relacionado é garantido que seja mais longo ou igual ao ciclo de vida do objeto com a referência unowned (por exemplo, em um ciclo de referências fortes onde um dos objetos tem um ciclo de vida claramente definido).

Comparação:

Característica weak unowned
Não possui Sim Sim
Incrementa o SC Não Não
Pode ser nil Sim (é automaticamente nulificado) Não (deve apontar para um objeto)
Segurança Mais segura em caso de desalocação Menos segura (erro fatal ao acessar um objeto desalocado)
Tipo Deve ser opcional Não pode ser opcional (padrão)
Uso Prevenir ciclos de referências fortes onde o objeto pode deixar de existir antes Prevenir ciclos de referências fortes onde o objeto garante sua existência

Exemplo de uso de weak para prevenir ciclo de referências fortes:

class Person {
    let name: String
    weak var apartment: Apartment? // referência fraca para evitar ciclo de retenção

    init(name: String) {
        self.name = name
        print("\(name) está sendo inicializado")
    }

    deinit {
        print("\(name) está sendo desinicializado")
    }
}

class Apartment {
    let unit: String
    var occupant: Person?

    init(unit: String) {
        self.unit = unit
        print("Apartamento \(unit) está sendo inicializado")
    }

    deinit {
        print("Apartamento \(unit) está sendo desinicializado")
    }
}

Exemplo de uso de unowned no contexto de capturar self em uma closure:

class HTMLElement {
    let name: String
    let text: String?

    lazy var asHTML: () -> String = {
        [unowned self] in // unowned self para evitar ciclo de retenção com a closure
        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) está sendo desinicializado")
    }
}