Logs a memory leak caused by a recently-encountered circular reference
- I almost didn’t recognize you because you changed your grammar, and I had to look for a long time
- Without further ado, let’s look at a piece of code
// The first part of the code here is a custom UIView, the view is a button, this view has an allSelectCallback, used to external calls when using class SomeView: UIView { var allSelectCallback: (() -> Void)? override init(frame: CGRect) { super.init(frame: frame)let btn = UIButton.init(frame: bounds)
addSubview(btn)
btn.addTarget(self, action: #selector(callBack), for: .touchUpInside)
}
@objc func callBack() { allSelectCallback? ()}}Copy the code
- Here’s the code to use the UIView above
Class Controller2: UIViewController {lazy var leakView:SomeView = {// Create the above Viewletview1 = SomeView.init(frame: CGRect.init(x: 100, y: 100, width: 100, height: Callback = {[weak self]} {[weak self]in
view1.isHidden = trueself? .dismiss(animated:true, completion: nil)
}
return view1
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(leakView)
}
}
Copy the code
- I even use weak self when I return it. What’s the problem?
- But take a closer look at the lazily loaded code
-
The view holds an allSelectCallback attribute
-
In the allSelectCallback callback, view.ishidden is called
-
The closure captures a reference to the View and holds it, so a reference loop occurs
-
As with the previous oc solution, weak var WeakView = view can solve the problem outside
-
The [weak self] in the code only weakly references the view of the controller, so the controller can be released normally. What is really not released is SomeView, and the leaking point is here