Strongly referenced variable may cause memory issues
I don't think strongly referenced variables to view controller cause any memory issues.
Normally views are deallocated before deallocating their view controller. For example, in in your code, when deallocating the view, ARC decreases the counter pointing to namelabel, so it passes from 2 to 1. Then, when deallocating the view controller it decreases the counter again, from 1 to 0. Once there are 0 references pointing to namelabel its removed.
create the label
when you need ,then call addsubView
to make an strong reference to it and make an weak reference to your member var like this:
class ViewController: UIViewController {
weak var label : UILabel?
override func viewDidLoad() {
super.viewDidLoad()
let label = UILabel()
view.addSubview(label)
self.label = label
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
print(label)
//click first Optional(<UILabel: 0x7fb562c3f260; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fb562c11c70>>)
//click second nil
label?.removeFromSuperview()
}
}
anyway while the viewcontroller
release ,the label will be release and view.subview
will be release too.
Demo
i wrote an easy demo make the ViewControllerTest
to be the rootviewcontroller
class Test{
weak var label:UILabel?
static let instance = Test()
}
class ViewControllerTest: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let item = UIBarButtonItem(title: "Test", style: .Plain, target: self, action: #selector(self.test))
self.navigationItem.rightBarButtonItem = item
}
func test(){
print(Test.instance.label)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let vc = ViewController()
self.navigationController?.pushViewController(vc, animated: true)
print(vc.nameLabel)
let test = Test.instance
test.label = vc.nameLabel
}
}
class ViewController: UIViewController {
var nameLabel : UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.whiteColor()
view.addSubview(nameLabel)
let item = UIBarButtonItem(title: "Test", style: .Plain, target: self, action: #selector(self.test))
self.navigationItem.rightBarButtonItem = item
}
func test(){
print(Test.instance.label)
}
}
The only thing I could gather from this was that although the label was removed from UIView, it still maintained a strong reference with the controller, hence permanent state in memory. Am I right?
No. There's no big issue here.
The label has no strong reference to the view controller — if it did, that would be a retain cycle and would cause both the label and the view controller to leak. For this very reason, a view should never keep a strong reference to its view controller.
Here, however, it's the other way around: the view controller has a strong reference to the label. That's fine. It's true that the label therefore stays in existence after it has been removed from its superview. But that might not be bad. In many cases, it's good! For example, suppose you intend to put the label back into the interface later; you will need to have retained it.
If you are sure you won't need to keep the label around later, then simply use an Optional wrapping a UILabel as your instance property. That way, you can assign nil
to the label instance property when you're done with it, and the label will go out of existence.
But in any case there is no leak here and you should just stop worrying. When the view controller goes out of existence, the label will go out of existence too. The label lived longer than it had to, but that's tiny and unimportant on the grand scale of things.