Middle
Quali tipi di riferimenti esistono in Swift?
sobes.tech AI
Risposta dell'AI
In Swift, ci sono tre principali tipi di riferimenti alle istanze delle classi:
-
Riferimento forte (Strong Reference):
- È il tipo di riferimento predefinito.
- Un riferimento forte aumenta il contatore di riferimenti dell'oggetto.
- L'oggetto non verrà rilasciato dalla memoria finché esiste almeno un riferimento forte.
- La principale causa di perdite di memoria nei cicli di riferimenti forti (
strong reference cycles).
class Person { let name: String init(name: String) { self.name = name } deinit { print("\(name) viene deallocato") } } var reference1: Person? = Person(name: "John") // reference1 ora è un riferimento forte, il contatore di riferimenti di Person aumenta -
Riferimento debole (Weak Reference):
- Viene dichiarato usando la parola chiave
weak. - Un riferimento debole non aumenta il contatore di riferimenti dell'oggetto.
- Viene usato per prevenire
strong reference cycles. - È sempre opzionale (
Optional), perché l'oggetto a cui punta il riferimento debole può essere deallocato in qualsiasi momento. Quando l'oggetto viene deallocato, il riferimento debole diventa automaticamentenil.
class Apartment { let unit: String weak var tenant: Person? // Riferimento debole init(unit: String) { self.unit = unit } deinit { print("Appartamento \(unit) viene deallocato") } } var john: Person? = Person(name: "John") var unit4A: Apartment? = Apartment(unit: "4A") john?.apartment = unit4A // Se Apartment avesse un riferimento forte a Person unit4A?.tenant = john // Riferimento debole // Dopo aver rimosso i riferimenti forti, gli oggetti verranno deallocati john = nil unit4A = nil // Output: "John viene deallocato", "Appartamento 4A viene deallocato" // Se tenant fosse un riferimento forte, si verificherebbe una perdita di memoria (cyclic cycle) - Viene dichiarato usando la parola chiave
-
Riferimento non posseduto (Unowned Reference):
- Viene dichiarato usando la parola chiave
unowned. - Simile al riferimento debole, non aumenta il contatore di riferimenti dell'oggetto.
- Viene usato anche per prevenire
strong reference cycles. - A differenza di
weak, non è opzionale (Optional) e presuppone che l'oggetto a cui si riferisce esisterà per tutta la "durata di vita" del riferimento non posseduto. - Se l'oggetto a cui si riferisce
unownedviene deallocato prima che il riferimentounowneddiventi invalido, si verificherà un errore di runtime (runtime error). - È adatto per situazioni in cui un oggetto esiste sempre finché un altro oggetto correlato esiste (ad esempio, "genitore-figlio", dove il genitore possiede il bambino, ma il bambino non possiede il genitore in modo forte).
class Customer { let name: String var card: CreditCard? init(name: String) { self.name = name } deinit { print("\(name) viene deallocato") } } class CreditCard { let number: Int unowned let customer: Customer // Riferimento non posseduto init(number: Int, customer: Customer) { self.number = number self.customer = customer // Assegnazione sicura in init } deinit { print("Carta #\(number) viene deallocata") } } var john: Customer? = Customer(name: "John Doe") john?.card = CreditCard(number: 1234_5678_9012_3456, customer: john!) // Rimuovere il riferimento forte a Customer john = nil // Output: "John Doe viene deallocato", "Carta #1234567890123456 viene deallocata" // Il riferimento non posseduto in CreditCard era valido finché customer esisteva. // Se CreditCard durasse più di Customer e si tentasse di accedere a customer tramite il riferimento non posseduto, si verificherebbe un errore. - Viene dichiarato usando la parola chiave
Differenza chiave tra weak e unowned:
weak: l'oggetto può esserenil. Usalo quando la durata di vita degli oggetti non è strettamente correlata (uno può esistere senza l'altro).unowned: l'oggetto non può esserenildopo l'inizializzazione. Usalo quando sei sicuro che l'oggetto referenziato esisterà almeno finché esiste l'oggetto che lo riferisce.