Sobes.tech
Middle

Quais são os tipos de referências em Swift?

sobes.tech IA

Resposta da IA

Em Swift, existem três tipos principais de referências:

  1. **Referência Forte (Strong Reference):

    • Aumenta o contador de referências do objeto.
    • Impede a desalocação do objeto enquanto existir pelo menos uma referência forte.
    • É o tipo padrão de referência em Swift.
    • A principal causa de ciclos de referências fortes.
  2. **Referência Fraca (Weak Reference):

    • Não aumenta o contador de referências.
    • Permite a desalocação do objeto se não houver mais referências fortes.
    • Declarada usando a palavra-chave weak.
    • Sempre é opcional (Optional), pois o objeto referenciado pode tornar-se nil.
    • Usada para prevenir ciclos de referências fortes, quando uma instância pode existir independentemente de outra.
    class Person {
        let name: String
        weak var apartment: Apartment? // Referência fraca
        init(name: String) {
            self.name = name
        }
        deinit { print("\(name) desalocado") }
    }
    
    class Apartment {
        let unit: String
        var tenant: Person? // Referência forte normal
        init(unit: String) {
            self.unit = unit
        }
        deinit { print("Apartamento \(unit) desalocado") }
    }
    
    var john: Person?
    var unit4A: Apartment?
    
    john = Person(name: "John Appleseed")
    unit4A = Apartment(unit: "4A")
    
    john!.apartment = unit4A
    unit4A!.tenant = john // Aqui surgiria um ciclo de referências fortes sem weak
    
    // As referências são anuladas, os objetos são desalocados
    john = nil
    unit4A = nil
    
  3. **Referência Não Propriedade (Unowned Reference):

    • Não aumenta o contador de referências.
    • Permite a desalocação do objeto se não houver mais referências fortes.
    • Declarada usando a palavra-chave unowned.
    • Não é opcional. Assume-se que o objeto referenciado sempre existirá enquanto a instância que contém a referência não própria existir.
    • Usar uma referência não própria em um objeto que já foi desalocado causará um erro em tempo de execução (crash).
    • Usada para prevenir ciclos de referências fortes, quando uma instância deve sempre existir enquanto outra existir, e não há possibilidade de um deles se tornar nil independentemente do outro (por exemplo, em ligações self em closures).
    class Customer {
        let name: String
        var card: CreditCard?
        init(name: String) {
            self.name = name
        }
        deinit { print("\(name) desalocado") }
    }
    
    class CreditCard {
        let number: UInt64
        unowned let customer: Customer // Referência não própria
        init(number: UInt64, customer: Customer) {
            self.number = number
            self.customer = customer
        }
        deinit { print("Cartão #\(number) desalocado") }
    }
    
    var john: Customer? = Customer(name: "John Appleseed")
    john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
    
    // Se o cliente for anulado, o cartão que faz referência a ele com unowned,
    // tornará inválido, mas não causará ciclo.
    john = nil // Ambos os objetos são desalocados
    

A escolha entre weak e unowned depende da natureza da relação entre os objetos: use weak quando um objeto pode existir sem o outro (Person sem Apartment), e unowned quando um objeto sempre deve existir enquanto o outro existir (CreditCard sempre pertence a Customer).