The UIView header states that superview property is strong
open var superview: UIView? { get }
But it behaves just like a weak property, i.e. if I create view1 and view2 and then call view1.addSubview(view2), and then save a strong ref to view2 only (not to view1), view1 will be deinited even though view2 references it through its superview property.
So, I wonder how it is implemented in reality.
Edit: for example, this code prints "deinit" (the ViewController instance is shown on the screen), which means that view1
is deinited, even though view2
should hold it strongly through the superview
property.
class View: UIView {
deinit {
print("deinit")
}
}
class ViewController: UIViewController {
var view2 = UIView()
override func viewDidLoad() {
super.viewDidLoad()
let view1 = View()
view1.addSubview(view2)
}
}
Oleg's answer is correct, but it's worth digging into this further. You're looking at this interface definition:
and you're assuming that means this is a strong property. It doesn't say that at all. It says
UIView
has a readonlysuperview
property. There is no setter, so you would not expect any memory management annotations (strong/weak/unowned).Even if it had a setter, for example,
UIView.backgroundColor
:This tells us exactly nothing about the memory management. There is no promise that this
UIColor
will be retained by the view. It is free to make its own copy. It is free extract information out of theUIColor
and generate some other object for its internal use (like aCGColor
), and throw this away. There is no promise thatbackgroundColor
has a backing ivar. This is free to be a computed setter.Some properties, like delegates, are marked
weak
:You generally can trust that these do not retain the object passed, but remember that these are informational, not guarantees. Consider this perfectly legal (and completely horrible) Swift:
myProp
claims to beweak
but actually does retain its value. You should never do this, but the point is that the language doesn't stop you.The take-away from all this is that if you care that an object continues to exist, it is your responsibility to maintain a strong reference to it. When you don't care if it exists, you should release your strong reference to it. You should avoid relying on some other object to maintain it for you.
(In practice, there are many real cases where it is incredibly handy to rely on the fact that some other object will hold something for you. For example, we of course rely heavily on the fact that Arrays hold strong references to their contents. But it's up to you to be certain that the container is promising that behavior if you need it. Looking at the interface is not sufficient.)
To the specific question of
UIView
, this is a computed property. While an implementation detail, here is roughly how it's implemented in iOS 10.1: