IOS closure loop reference (Swift)
1. When will a closure circular reference be formed?
When the closure captures its own reference and destroys it at the same time, it will lead to circular reference.
If you are not familiar with closures, refer to this article.
Swift getting started tutorial Series 6-closures
For example:
Description is declared as a closure, which is a lazy variable (the lazy variable is initialized only when needed). The function of this closure is to call the instance function of the class.
Class CSDN {var name: String? Lazy var description :()-> () = {self. print ()} func print () {println (Closure call function)} init (name: String ?) {Self. name = name} deinit {println (memory to be released)} class ViewController: UIViewController {var instance: CSDN? = CSDN (name: hello hwc) override func viewDidLoad () {super. viewDidLoad () instance ?. Description () instance = nil // The Destructor should be called here, but it is not called because of loop reference} override func didReceiveMemoryWarning () {super. didreceivemorywarning ()}}
Output
Closure call Function
Memory Structure at this time
In this case, the memory reference count of instance is 2, and the closure reference count is 1.
Then, disconnect a strong reference from instance = nil,
At this time, the two memories are referenced cyclically and the reference count is 1, so the memory cannot be released.
2. Use the capture list to solve the problem
The elements in the capture list are referenced by weak references and helpless references. For those unfamiliar with the two concepts, refer to this article.
Solve the circular reference (Swfit) between ARC instances in IOS)
Capture List format
Add the [unowned variable to be captured] to the front of the closure.
For example
Lazy var print {
[Unowned self] in
}
In this way, we will rewrite this project.
Class CSDN {var name: String? Lazy var description :()-> () = {[unowned self] in self. print ()} func print () {println (Closure call function)} init (name: String ?) {Self. name = name} deinit {println (memory to be released)} class ViewController: UIViewController {var instance: CSDN? = CSDN (name: hello hwc) override func viewDidLoad () {super. viewDidLoad () instance ?. Description () instance = nil // memory will be released here} override func didReceiveMemoryWarning () {super. didreceivemorywarning ()}}
Output
Memory to be released when the closure function calls
Memory Structure at this time
At this time, the closure and instance memory reference count are both 1
Then disconnect a strong reference (instance = nil)
In this case, the instance memory reference count is 0, the closure reference count is 1, the instance memory is released, the closure reference count is 0, and the closure memory is released.
My swift Column