Unowned ссылки и неявно развернутые optional свойства
👋 В этой статье рассмотрим эффективность применения неявно развернутых опциональных свойств для создания взаимозависимости в классах без риска возникновения циклических ссылок.
Зачем это нужно?
Представим ситуацию, когда есть модель данных, в которой каждый отдел имеет своего руководителя, а каждый руководитель относится к конкретному отделу. Это прямая и естественная взаимосвязь, но как ее реализовать в Swift, избегая циклических ссылок и обеспечивая корректное управление памятью? Ответ кроется в комбинировании неявно развернутых опциональных свойств с обычными свойствами.
Department и Employee
Рассмотрим два класса, Department и Employee. В нашем случае класс Department будет хранить неявно развернутое опциональное свойство, представляющее руководителя, а класс Employee будет содержать unowned ссылку на Department.
class Department { let name: String var head: Employee! init(name: String, headName: String) { self.name = name self.head = Employee(name: headName, department: self) } } class Employee { let name: String unowned let department: Department init(name: String, department: Department) { self.name = name self.department = department } }
Как это работает?
- Некоторые определения. Класс Department имеет два свойства: неизменяемое name и изменяемое head, которое является неявно развернутым опционалом. Это значит, что по умолчанию оно имеет значение nil, но после инициализации можно без опаски с ним работать, не применяя оператор развертки.
- Инициализация. При создании экземпляра Department передаем имя руководителя в инициализатор и тут же создаем экземпляр Employee, связывая его с руководителем отдела.
- Устранение циклических ссылок. Класс Employee хранит unowned ссылку на отдел. Это значит, что, даже если Employee ссылается на Department, это не создает циклическую ссылку: если Department будет уничтожен, Employee не будет удерживать ссылку на него, что позволяет избежать утечки памяти.
Пример использования
Теперь, создавая объект класса Department, можно сразу получить информацию о руководителе отдела.
let department = Department(name: "Mobile Development", headName: "Ivanov") print("The head of the \(department.name) department is \(department.head.name).")
Такой подход не только помогает избежать циклических ссылок, но и делает код более чистым и читаемым, позволяя разработчикам работать с зависимостями между объектами без излишних разверток.
👍 Ставьте лайк, если хотите, чтобы подобные посты выходили чаще.