Middle
Какви видове връзки съществуват в Swift?
sobes.tech AI
Отговор от AI
В Swift има три основни вида референции към екземпляри на класове:
-
Силна референция (Strong Reference):
- Това е подразбиращият се тип референция.
- Силната референция увеличава брояча на референциите на обекта.
- Обектът няма да бъде освободен от паметта, докато има поне една силна референция към него.
- Основната причина за течове на памет при циклични силни референции (
strong reference cycles).
class Person { let name: String init(name: String) { self.name = name } deinit { print("\(name) се освобождава") } } var reference1: Person? = Person(name: "John") // reference1 сега е силна референция, броячът на референциите на Person се увеличава -
Слаба референция (Weak Reference):
- Обявява се с ключовата дума
weak. - Слабата референция не увеличава брояча на референциите на обекта.
- Използва се за предотвратяване на
strong reference cycles. - Винаги е опционална (
Optional), защото обектът, към който сочи, може да бъде деинициализиран по всяко време. При деинициализация, слабата референция автоматично ставаnil.
class Apartment { let unit: String weak var tenant: Person? // Слаба референция init(unit: String) { self.unit = unit } deinit { print("Апартамент \(unit) се освобождава") } } var john: Person? = Person(name: "John") var unit4A: Apartment? = Apartment(unit: "4A") john?.apartment = unit4A // Ако апартаментът имаше силна референция към John unit4A?.tenant = john // Слаба референция // След изтриване на силните референции, обектите ще бъдат деинициализирани john = nil unit4A = nil // Изход: "John се освобождава", "Апартамент 4A се освобождава" // Ако tenant беше силна референция, щеше да се получи теч на памет (strong cycle) - Обявява се с ключовата дума
-
Несвързана референция (Unowned Reference):
- Обявява се с ключовата дума
unowned. - Подобно на слабата референция, не увеличава брояча на референциите.
- Използва се също за предотвратяване на
strong reference cycles. - За разлика от
weak, не е опционална (Optional) и предполага, че обектът, към който сочи, ще съществува през цялото "животно" на референцията. - Ако обектът, към който сочи
unownedреференцията, бъде деинициализиран предиunownedреференцията да стане невалидна, ще възникне грешка по време на изпълнение (runtime error). - Подходящ е за ситуации, когато един обект винаги съществува, докато съществува друг свързан обект (например, връзка "родител-дете", където родителят притежава детето, но детето не притежава родителя силно).
class Customer { let name: String var card: CreditCard? init(name: String) { self.name = name } deinit { print("\(name) се освобождава") } } class CreditCard { let number: Int unowned let customer: Customer // Несвързана референция init(number: Int, customer: Customer) { self.number = number self.customer = customer // Назначаването на несвързана референция в init е безопасно } deinit { print("Карта #\(number) се освобождава") } } var john: Customer? = Customer(name: "John Doe") john?.card = CreditCard(number: 1234_5678_9012_3456, customer: john!) // Изтриване на силната референция към Customer john = nil // Изход: "John Doe се освобождава", "Карта #1234567890123456 се освобождава" // Несвързаната референция към customer в CreditCard беше валидна, докато customer съществуваше. // Ако CreditCard живееше по-дълго от Customer и се опитвахме да достъпим customer чрез несвързаната референция, щеше да възникне грешка. - Обявява се с ключовата дума
Ключовата разлика между weak и unowned:
weak: обектът може да бъдеnil. Използвайте, когато жизненият цикъл на обектите не е строго свързан (един може да съществува без другия).unowned: обектът не може да бъдеnilслед инициализация. Използвайте, когато сте сигурни, че реферираният обект ще съществува поне докато съществува рефериращият обект.