Adding and Removing Subviews(增加和删除子视图的官方文档)

来源:互联网 发布:淘宝搞笑好评大全 编辑:程序博客网 时间:2024/05/17 02:40

现在觉得看官方文档很又用,几乎你所有的问题都可以通过官方文档解决。视图架构和展现在网上很少有介绍,就算有也不太清晰。现在把官方的文档放上来,备案,读着清晰多了。


Adding and Removing Subviews

Interface Builder is the most convenient way to build view hierarchies because you assemble your views graphically, see the relationships between the views, and see exactly how those views will appear at runtime. When using Interface Builder, you save your resulting view hierarchy in a nib file, which you load at runtime as the corresponding views are needed.

If you prefer to create your views programmatically instead, you create and initialize them and then use the following methods to arrange them into hierarchies:

  • To add a subview to a parent, call the addSubview: method of the parent view. This method adds the subview to the end of the parent’s list of subviews.
  • To insert a subview in the middle of the parent’s list of subviews, call any of theinsertSubview:... methods of the parent view. Inserting a subview in the middle of the list visually places that view behind any views that come later in the list.
  • To reorder existing subviews inside their parent, call the bringSubviewToFront:, sendSubviewToBack:, or exchangeSubviewAtIndex:withSubviewAtIndex: methods of the parent view. Using these methods is faster than removing the subviews and reinserting them.
  • To remove a subview from its parent, call the removeFromSuperview method of the subview (not the parent view).

When adding a subview to its parent, the subview’s current frame rectangle denotes its initial position inside the parent view. A subview whose frame lies outside of its superview’s visible bounds is not clipped by default. If you want your subview to be clipped to the superview’s bounds, you must explicitly set the clipsToBounds property of the superview to YES.

The most common example of adding a subview to another view occurs in theapplication:didFinishLaunchingWithOptions: method of almost every application. Listing 3-1 shows a version of this method that installs the view from the application’s main view controller into the application window. Both the window and the view controller are stored in the application’s main nib file, which is loaded before the method is called. However, the view hierarchy managed by the view controller is not actually loaded until theview property is accessed.

Listing 3-1  Adding a view to a window

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{    // Override point for customization after application launch.     // Add the view controller's view to the window and display.    [window addSubview:viewController.view];    [window makeKeyAndVisible];     return YES;}


Listing 3-2 shows the viewDidLoad method of theTransitionsViewController class from the UICatalog sample application. The TransitionsViewController class manages the animations associated with transitioning between two views. The application’s initial view hierarchy (consisting of a root view and toolbar) is loaded from a nib file. The code in the viewDidLoad method subsequently creates the container view and image views used to manage the transitions. The purpose of the container view is to simplify the code needed to implement the transition animations between the two image views. The container view has no real content of its own.Another common place where you might add subviews to a view hierarchy is in theloadView or viewDidLoad methods of a view controller. If you are building your views programmatically, you put your view creation code in theloadView method of your view controller. Whether you create your views programmatically or load them from a nib file, you could include additional view configuration code in theviewDidLoad method.

Listing 3-2  Adding views to an existing view hierarchy

- (void)viewDidLoad{    [super viewDidLoad];     self.title = NSLocalizedString(@"TransitionsTitle", @"");     // create the container view which we will use for transition animation (centered horizontally)    CGRect frame = CGRectMake(round((self.view.bounds.size.width - kImageWidth) / 2.0),                                                        kTopPlacement, kImageWidth, kImageHeight);    self.containerView = [[[UIView alloc] initWithFrame:frame] autorelease];    [self.view addSubview:self.containerView];     // The container view can represent the images for accessibility.    [self.containerView setIsAccessibilityElement:YES];    [self.containerView setAccessibilityLabel:NSLocalizedString(@"ImagesTitle", @"")];     // create the initial image view    frame = CGRectMake(0.0, 0.0, kImageWidth, kImageHeight);    self.mainView = [[[UIImageView alloc] initWithFrame:frame] autorelease];    self.mainView.image = [UIImage imageNamed:@"scene1.jpg"];    [self.containerView addSubview:self.mainView];     // create the alternate image view (to transition between)    CGRect imageFrame = CGRectMake(0.0, 0.0, kImageWidth, kImageHeight);    self.flipToView = [[[UIImageView alloc] initWithFrame:imageFrame] autorelease];    self.flipToView.image = [UIImage imageNamed:@"scene2.jpg"];}

Important Superviews automatically retain their subviews, so after embedding a subview it is safe to release that subview. In fact, doing so is recommended because it prevents your application from retaining the view one time too many and causing a memory leak later. Just remember that if you remove a subview from its superview and intend to reuse it, you must retain the subview again. TheremoveFromSuperview method autoreleases a subview before removing it from its superview. If you do not retain the view before the next event loop cycle, the view will be released.

For more information about Cocoa memory management conventions, seeAdvanced Memory Management Programming Guide.


When you add a subview to another view, UIKit notifies both the parent and child views of the change. If you implement custom views, you can intercept these notifications by overriding one or more of thewillMoveToSuperview:, willMoveToWindow:, willRemoveSubview:, didAddSubview:, didMoveToSuperview, or didMoveToWindow methods. You can use these notifications to update any state information related to your view hierarchy or to perform additional tasks.

After creating a view hierarchy, you can navigate it programmatically using thesuperview and subviews properties of your views. The window property of each view contains the window in which that view is currently displayed (if any). Because the root view in a view hierarchy has no parent, itssuperview property is set to nil. For views that are currently onscreen, the window object is the root view of the view hierarchy.

Hiding Views

To hide a view visually, you can either set its hidden property to YES or change its alpha property to 0.0. A hidden view does not receive touch events from the system. However, hidden views do participate in autoresizing and other layout operations associated with the view hierarchy. Thus, hiding a view is often a convenient alternative to removing views from your view hierarchy, especially if you plan to show the views again at some point soon.

Important If you hide a view that is currently the first responder, the view does not automatically resign its first responder status. Events targeted at the first responder are still delivered to the hidden view. To prevent this from happening, you should force your view to resign the first responder status when you hide it. For more information about the responder chain, seeEvent Handling Guide for iOS.


If you want to animate a view’s transition from visible to hidden (or the reverse), you must do so using the view’salpha property. The hidden property is not an animatable property, so any changes you make to it take effect immediately.

Locating Views in a View Hierarchy

There are two ways to locate views in a view hierarchy:

  • Store pointers to any relevant views in an appropriate location, such as in the view controller that owns the views.
  • Assign a unique integer to each view’s tag property and use the viewWithTag: method to locate it.

Storing references to relevant views is the most common approach to locating views and makes accessing those views very convenient. If you used Interface Builder to create your views, you can connect objects in your nib file (including the File’s Owner object that represents the managing controller object) to one another usingoutlets. For views you create programmatically, you can store references to those views in private member variables. Whether you use outlets or private member variables, you are responsible for retaining the views as needed and then releasing them as well. The best way to ensure objects are retained and released properly is to usedeclared properties.

Tags are a useful way to reduce hard-coded dependencies and support more dynamic and flexible solutions. Rather than storing a pointer to a view, you could locate it using its tag. Tags are also a more persistent way of referring to views. For example, if you wanted to save the list of views that are currently visible in your application, you would write out the tags of each visible view to a file. This is simpler than archiving the actual view objects, especially in situations where you are tracking only which views are currently visible. When your application is subsequently loaded, you would then re-create your views and use the saved list of tags to set the visibility of each view, and thereby return your view hierarchy to its previous state.