Subview and Superview
Now some or all of a subview can appear outside its superview, and a view can overlap another view and be drawn partially or totally in front of it without being its subview.
Nevertheless, a view’s position in the view hierarchy does affect how it is drawn. Most important, a view’s position in the view hierarchy dictates the order in which it is drawn. Sibling subviews of the same superview have a layering order: one is “further back” than the other. This will make no visible difference if there is no overlap, but the subview that is “further back” is drawn first, so if there is overlap, it will appear to be behind its sibling. Similarly, a superview is “further back” than its subviews; the superview is drawn first, so it will appear to be behind its subviews.
This layering order can be governed in the nib either by choosing from the Editor->Arrangement menu (Send to Front, Send to Back, Send Forward, Send Backward) or by arranging the views in the expanded dock. In code, there are methods for arranging the sibling order of views (which we’ll come to in a moment).
Here are some other effects of the view hierarchy:
1)If a view is removed from or moved within its superview, its subviews go with it.
2)If a view’s size is changed, its subviews can be resized automatically.
3)A view’s degree of transparency is inherited by its subviews.
4)A view can optionally limit the drawing of its subviews so that any parts of them outside the view are not shown. This is called clipping and is set with the view’s clipsToBounds property.
5)A superview owns its subviews, in the memory-management sense, much as an NSArray owns its elements; it retains them and is responsible for releasing a subview when that subview ceases to be its subview (it is removed from the collection of this view’s subviews) or when it itself goes out of existence.
A UIView has a superview property (a UIView) and a subviews property (an NSArray of UIViews, in back-to-front order), allowing you to trace the view hierarchy in code. There is also a method isDescendantOfView: letting you check whether one view is a subview of another at any depth. If you need a reference to a particular view, you will probably arrange this beforehand as an instance variable, perhaps through an outlet.
Alternatively, a view can have a tag (its tag property, an integer), and can then be referred to by sending any view further up the view hierarchy the viewWithTag: message. Seeing that all tags of interest are unique within their section of the hierarchy is up to you.
The method addSubview: makes one view a subview of another; removeFromSuperview takes a subview out of its superview’s view hierarchy. In both cases, if the superview is part of the visible interface, the subview will appear or disappear; and of course this view may itself have subviews that accompany it. Just remember that removing a subview from its superview releases it; if you intend to reuse that subview later on, you will wish to retain it first. This is often taken care of through a property with a retain policy.
Events inform a view of these dynamic changes. To respond to these events requires subclassing. Then you’ll be able to override any of didAddSubview: and willRemoveSubview:, didMoveToSuperview and willMoveToSuperview:, didMoveToWindow and willMoveToWindow:.
When addSubview: is called, the view is placed last among its superview’s subviews; thus it is drawn last, meaning that it appears frontmost. A view’s subviews are indexed, starting at 0, which is rearmost. There are additional methods for inserting a subview at a given index (insertSubview:atIndex:), or below (behind) or above (in front of) a specific view (insertSubview:belowSubview:, insertSubview:aboveSubview:); for swapping two sibling views by index (exchangeSubviewAtIndex:withSubviewAtIndex:); and for moving a subview all the way to the front or back among its siblings (bringSubviewToFront:, sendSubviewToBack:).
Oddly, there is no command for removing all of a view’s subviews at once. However, a view’s subviews array is an immutable copy of the internal list of subviews, so it is legal to cycle through it and remove each subview one at a time:
for (UIView* v in view.subviews)
[v removeFromSuperview];