## Retain cycle

1. [Automatic Reference Counting](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/automaticreferencecounting/)

Retain cycle (circular reference) возникает, когда два или более объекта ссылаются друг на друга, не позволяя их деаллоцировать. В результате могут возникать утечки памяти, что приводит к тому, что ваше приложение потребляет больше памяти, чем необходимо.

### Друг на друга ссылаются

<details><summary>Open</summary>
<p>

Наглядная иллюстрация приведенного ниже кода:

![SelfRefCycle](/pictures/Memory/SelfRefCycle.jpg?raw=true)

Имплементация retain cycle, когда объекты ссылаются друг на друга:

```swift
final class Person {
    let firstName: String
    let lastName: String
    var parent: Person?
    var kid: Person?
    
    init(firstName: String, lastName: String) {
        self.firstName = firstName
        self.lastName = lastName
    }
    deinit {
        print("Person \(firstName) deinit called")
    }
}

var kidJohn: Person? = Person(firstName: "John", lastName: "Deere")
var parentSara: Person? = Person(firstName: "Sara", lastName: "Deere")

kidJohn?.parent = parentSara
parentSara?.kid = kidJohn
```

Установим экземпляры класса `kidJohn` и `parentSara` nil:

```swift
// deinit не вызовется
kidJohn = nil
parentSara = nil
```

Экземпляры (`kidJohn` и `parentSara`) не будут освобождены, нет сообщений «deinit», произойдет утечка памяти.

Почему это происходит? Для этого рассмотрим визуальный пример:

![SelfRefCycle2](/pictures/Memory/SelfRefCycle2.jpg?raw=true)

#### Решение проблемы

Использование так называемых [weak (слабых)](./3.1.3.1.4.4%20Weak.md) ссылок — это способ избежать retain cycle. Если вы объявляете ссылку слабой ([weak](./3.1.3.1.4.4%20Weak.md))), то эта ссылка не препятствует освобождению экземпляра. Давайте изменим наш код и посмотрим, что произойдет:

```swift
weak var parent: Person?
weak var kid: Person?
```

![SelfRefCycle3](/pictures/Memory/SelfRefCycle3.jpg?raw=true)

Остаются только слабые ссылки, а экземпляры будут удалены.

</p>
</details>



### Ссылка на самого себя

<details><summary>Open</summary>
<p>

![ClosureRefCycle](/pictures/Memory/ClosureRefCycle.jpg?raw=true)

Если мы напишем следующий код:

```swift
final class Person {
    let firstName: String
    let lastName: String
    
    // deinit вызовется
    // тк fullNameVarFromClosure это не closure, это вычисляемое свойство
    // которое возвращает String
    // оно по дефолту @noescape и никаких capture list здесь не нужно
    // [ссылка](https://michael-kiley.medium.com/why-your-lazy-vars-arent-creating-strong-reference-cycles-in-ios-d512ff2c9403)
    lazy var fullNameVarFromClosure : String = {
        return self.firstName + " " + self.lastName
    }()
    // deinit вызовется
    var fullNameComputedVar: String {
        self.firstName + " " + self.lastName
    }
    // deinit не вызовется
    lazy var fullNameClosure: () -> String = {
        return self.firstName + " " + self.lastName
    }

    // deinit не вызовется
    lazy var closure: () -> Void = { [self] in
        self.closure()
    }
    
    init(firstName: String, lastName: String) {
        self.firstName = firstName
        self.lastName = lastName
    }
    deinit {
        print("Person \(firstName) deinit called")
    }
}

var personJohn: Person? = Person(firstName: "John", lastName: "Deere")
// deinit вызовется
print(personJohn!.fullNameVarFromClosure)
personJohn = nil
// deinit не вызовется
print(personJohn!.fullNameClosure)
personJohn = nil
```

Несмотря на то, что внутри `fullNameVar` мы ссылаем на самого себя `deinit` будет вызван! Причина в том что `fullNameVar` это [value тип](/5%20Swift/5.3%20DataRepresentations/5.3.1%20DataTypes/5.3.1.4%20ValueTypes/).

А `fullNameClosure` - это [closure](/5%20Swift/5.3%20DataRepresentations/5.3.1%20DataTypes/5.3.1.3%20ReferenceTypes/Closure.md), то есть [reference тип](/5%20Swift/5.3%20DataRepresentations/5.3.1%20DataTypes/5.3.1.3%20ReferenceTypes/).

#### Решение проблемы

```swift
lazy var fullNameClosure: () -> String = { [weak self] in
    return self!.firstName + " " + self!.lastName
}
```

</p>
</details>

---

[3.1.3.1.3 Autoreleasepool Theme](../3.1.3.1.3%20Autoreleasepool.md) | [Back To iTWiki Contents](https://github.com/eldaroid/iTWiki) | [3.1.3.1.4.2 Strong Reference Theme](./3.1.3.1.4.2%20Strong.md)