Sobes.tech
Middle

Para que serve o tipo de referências unowned?

sobes.tech IA

Resposta da IA

Referências unowned são necessárias para resolver ciclos de referência (retain cycles) entre objetos, quando ambos os objetos têm uma referência forte entre si, mas um dos objetos tem um ciclo de vida mais curto ou igual ao outro.

unowned é usado quando se sabe que o objeto referenciado não será nil durante toda a vida do objeto que contém a referência. Ao contrário de weak, ao aceder a uma referência unowned não se usa Optional. Se o objeto ao qual unowned se refere for desalocado antes do objeto com a referência unowned, ocorrerá um crash.

Exemplo de uso em closures:

class Person {
    let name: String
    var apartment: Apartment?

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

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

class Apartment {
    let unit: String
    // Usamos unowned porque sabemos que
    // o Apartment não pode existir sem a Person
    // (neste contexto). A Person pode ser nil,
    // mas se o Apartment existir, a Person também existe.
    unowned let tenant: Person?

    init(unit: String, tenant: Person?) {
        self.unit = unit
        self.tenant = tenant
        print("Apartamento \(unit) está a ser inicializado")
    }

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

var john: Person?
var unit4A: Apartment?

john = Person(name: "John Appleseed")
// Neste exemplo, tenant pode ser nil, por isso
// usa-se uma referência unowned opcional
unit4A = Apartment(unit: "4A", tenant: john)

john!.apartment = unit4A

// Rompemos as referências fortes para verificar a desinicialização
john = nil
unit4A = nil

Neste exemplo, Person tem uma referência forte a Apartment (var apartment: Apartment?). Apartment poderia ter uma referência forte a Person, o que criaria um ciclo. No entanto, neste contexto, Apartment não pode existir sem Person (que o aluga), portanto a referência de Apartment a Person é unowned. Assim, ao colocar john = nil, Person é desalocado, e por sua vez (uma vez que não há referências fortes a Apartment) também é desalocado Apartment.

Principais diferenças com weak:

  • Ciclo de vida: unowned é usado quando o objeto referenciado tem um ciclo de vida igual ou mais longo. weak é usado quando o objeto referenciado pode ser desalocado mais cedo.
  • Optional: unowned não é opcional (a menos que seja declarado como unowned optional). weak é sempre opcional.
  • Segurança: Acesso a uma propriedade com referência unowned a um objeto já desalocado causará um crash. Acesso a uma referência weak retornará nil.

Assim, unowned é uma referência não proprietária (non-owning) que é usada quando se garante a existência do objeto referenciado enquanto o objeto com a referência unowned existir.