ARC (Automatic Reference Counting) is the automatic memory management system in Swift. Each time a strong reference to an object is created, the counter increases; when it is removed, the counter decreases. When the count reaches zero, the object is deallocated.
Retain cycle is a situation when objects reference each other with strong references and are never deallocated.
Ways to avoid:
protocol SomeDelegate: AnyObject { } class Owner { weak var delegate: SomeDelegate? }
[weak self] or [unowned self]:class Example { var closure: (() -> Void)? func setup() { closure = { [weak self] in self?.doSomething() } } func doSomething() { } }
What is the difference between [weak self] and [unowned self] inside a closure? Which type of references to use and when?
Answer:
[weak self] creates an optional reference; self can be nil, so usually safe unwrapping self? is used.[unowned self] creates a non-optional reference and does NOT increase the counter; if the object has already been deallocated and access occurs, it will crash.[unowned self].Example:
someClosure = { [weak self] in self?.doTask() } // or (if self is guaranteed to outlive the closure): someClosure = { [unowned self] in doTask() }
Story
In the project, a retain cycle situation arose between the ViewController and its closure associated with handling taps. The ViewController held a reference to the closure, which captured self with a strong reference. As a result, the controller and all its data were not deallocated after the screen was closed. The problem was resolved by implementing
[weak self]in the closure.
Story
Implementation of the delegate pattern between two objects. The delegate was declared as a strong property. Consequently, when attempting to delete the main object from memory, it was not deallocated, leading to a memory leak. After changing the delegate to weak, the issue disappeared.
Story
For animation, a closure was used inside UIView. The closure captured self using
[unowned self]. When the view was removed before the animation completed, the application crashed due to access to already deallocated self. The solution was to use[weak self]and mandatory checking for non-nil self within the closure.