iOS开发之-Custom View Controllers

本文详细介绍了 ViewController 的创建、内存管理、界面显示属性配置、编程方式创建视图、卸载视图后的清理、界面旋转过程及响应、支持多种方向的方法等内容,帮助开发者深入理解 ViewController 的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

View Controller Basics



Implementation Checklist for Custom View Controllers


1. For any custom view controllers you create, there are several tasks that you should always handle:


You must configure the view to be loaded by your view controller; 
You must decide which orientations your view controller supports; 
You must clean up the memory that is managed by your view controller; 


Anatomy of a Custom View Controller



Understanding the View Management Cycle


1. The load cycle occurs whenever some part of your application asks the view controller for a pointer to its view object and that object is not currently in memory. When that happens, the view controller loads the view into memory and stores a pointer to the view for future reference.


2. If your application receives a low-memory warning at some point in the future, the view controller may subsequently try to unload the view. During the unload cycle, the view controller attempts to release its view object and return the view controller to its initial viewless state. If it is able to release the view, the view controller remains without a view object until the view is once again requested, at which point the load cycle begins again.


3. The steps that occur during the load cycle are as follows:


 (1) Some part of your application asks for the view in the view controller’s view property.
 (2) If the view is not currently in memory, the view controller calls its loadView method.
 (3) The loadView method does one of the following:

       If you override this method, your implementation is responsible for creating all necessary views andassigning a        non-nil value to the view property.

       If you do not override this method, the default implementation uses the nibName and nibBundle properties of            the view controller to try to load the view from the specified nib file. 

       If the specified nib file is not found, it looks for a nib file whose name matches the name of the view controller            class and loads that file.

       If no nib file is available, the method creates an empty UIView object and assigns it to the view property.
 (4) The view controller calls its viewDidLoad method to perform any additional load-time tasks.



4. The steps that occur during the unload cycle are as follows:


  (1) The application receives a low-memory warning from the system.

  (2) Each view controller calls its didReceiveMemoryWarning method:

      If you override this method, you should use it to release any custom data that your view controller object no               longer needs. You should not use it to release your view controller’s view. You must call super at some point in         your implementation to perform the default behavior.

      The default implementation releases the view only if it determines that it is safe to do so.

      If you do override didReceiveMemoryWarning, always call super to give the inherited version of the method a             chance to release the view.

  (3) If the view controller releases its view, it calls its viewDidUnload method. You can override this method to                   perform any additional cleanup required for your views and view hierarchy.




Defining a Custom View Controller Class


Creating the View for Your View Controller


1. Creating the View in Interface Builder

There are two ways to configure a nib file for use with a view controller:

  • Create a detached nib file by storing the view in a nib file by itself.
  • Create an integrated nib file by storing both the view and view controller in the same nib file.
Detached nib files offer a more robust solution, especially in the realm of memory management. During a low-memory condition, the contents of a detached nib file can be purged from memory as needed without affecting the state of the owning view controller object. The same is not true in the case of an integrated nib file, the contents of which must stay in memory until all nib-file objects are no longer needed.


2. The configuration of the detached nib file:
  • Set the class name of the File’s Owner placeholder to your view controller class.
  • Make sure the view outlet of the File’s Owner placeholder is connected to the top-level View object in the nib file.
  • Configure the view itself and add any subviews you need to display your application’s content.
  • Save the nib file.
This view outlet is defined by the UIViewController class and inherited by all view controller objects.

3. If you are creating your view controller programmatically, pass the name of the nib file to the initWithNibName:bundle: method when you initialize your view controller object. 

If you are loading your view controller object from a separate nib file (one other than the one containing the view), use Interface Builder to set the value NIB Name attribute of the view controller object to the name of your view’s nib file.

4. For a detached nib file, the actual loading of the nib file occurs automatically when the view property of the view controller object is accessed and the view is not currently in memory. The default loadView method uses the nibName and nibBundle properties to locate the desired nib file and load its contents into memory.




Storing the View and View Controller in the Same Nib File


1. If your application has only one screen, you can include both the views for that screen and the view controller that manages them in the same nib file. Storing views and custom view controller objects in the same nib file is generally not recommended because it often prevents the system from unloading the views in low-memory situations. However, if the view itself is never going to be unloaded, including it in the same nib file as its view controller object might make the most sense.





2. Whenever you add objects to the top-level of your nib file, you should always connect those objects to outlets somewhere else in the nib file.  In addition, because top-level objects are retained and then autoreleased, if you did not retain the object, it might possibly be released before you had a chance to use it.


Configuring the View Display Attributes in Interface Builder



Creating the View Programmatically


1. If you prefer to create views programmatically, you do so from your view controller’s loadView method.Your implementation of this method should do the following:

  • Create a root view object that is sized to fit the screen.
        a. You typically define the frame for this view to match the size of the application window, which itself should fill             the screen. However, the view controller also adjusts the frame size as needed to accommodate the                           presence of assorted views, such as the system status bar, a navigation bar, or a tab bar.
  • Create any additional subviews and add them to the root view. 
        a. Create and initialize the view. For system views, you typically use the initWithFrame: method to specify the                  initial size and position of the view.
        b. Add the view to a parent view using the addSubview: method.
        c. Release the view by calling its release method.

  • Assign the root view to the view property of your view controller.
  • Release the root view.

2. Once you add a view to your view hierarchy or save a reference to it

- (void)loadView {
 
    self.wantsFullScreenLayout = YES;
 
    MetronomeView *view = [[MetronomeView alloc]
                           initWithFrame:[UIScreen mainScreen].applicationFrame];
    view.metronomeViewController = self;
    self.view = view;
    self.metronomeView = view;
 
    [view release];
}


Cleaning Up After Unloading a View


1. After it is loaded into memory, a view controller’s view remains in memory until a low-memory condition occurs or the view controller itself is deallocated. In the case of a low-memory condition, the default UIViewController behavior is to release the view object stored in the view property if that view is not currently being used.

2. However, if your custom view controller class stores outlets or pointers to any views in the view hierarchy, you must also release those references when the top-level view object is released. Failure to do so prevents those objects from being removed from memory right away and could potentially cause memory leaks later if you subsequently overwrite any pointers to them.

3. There are two places where your view controller should always clean up any references to view objects:

The dealloc method
The viewDidUnload method


Managing Memory Efficiently





Managing a View Controller’s Interface Orientation



Understanding the Rotation Process

1. When the orientation of an iOS–based device changes, the system sends out a UIDeviceOrientationDidChangeNotification notification to let any interested parties know that the change occurred. By default, the UIKit framework intercepts this notification and uses it to update your interface orientation automatically. This means that with only a few exceptions, you should not need to handle this notification at all. Instead, all you need to do is implement the appropriate methods in your view controller classes to respond to orientation changes.

2. The window object does much of the work associated with changing the current orientation. However, it works in conjunction with the application’s view controllers to determine whether an orientation change should occur at all

3. The window object works only with the frontmost view controller whose view was displayed using one of the mechanisms 

4. Because your custom methods are called during the rotation operation, you should avoid performing any time-consuming operations there. You should also avoid replacing your entire view hierarchy with a new set of views. There are better ways to provide unique views for different orientations, such as presenting a new view controller modally


Declaring the Supported Interface Orientations

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation
{
   if ((orientation == UIInterfaceOrientationPortrait) ||
       (orientation == UIInterfaceOrientationLandscapeLeft))
      return YES;
 
   return NO;
}

If the view managed by your view controller supports orientations other than the default portrait orientation, you must override the shouldAutorotateToInterfaceOrientation: method and indicate which orientations your view supports.


Configuring Your Views to Support Multiple Orientations

1. When the user interface changes orientation, the bounds of the affected views are modified automatically according to their autoresizing mask.

2.  Each view adjusts its own bounds and then asks each of its subviews to resize itself based on its autoresizing behaviors. 


Responding to Orientation Changes

1. The reason you might want to respond to orientation changes is to make adjustments to your view hierarchy.

Show or hide views that are specific to a particular orientation.
Adjust the position or size of views based on the new orientation.
Update other parts of your application to reflect the orientation change.


2. Responding to Orientation Changes in One Step

sequence of events occurs:

  1. The window detects that a change in the device orientation has occurred.
  2. The window looks for an appropriate view controller and calls itsshouldAutorotateToInterfaceOrientation: method to determine if it supports the new orientation.For example, the tab bar controller allows orientation changes only if all of its managed view controllers support the new orientation.
  3. If the new orientation is supported, the window calls the view controller’swillRotateToInterfaceOrientation:duration: method.Container view controllers forward this message on to the currently displayed custom view controller. You can override this method in your custom view controllers to hide views or make other changes to your view layout before the interface is rotated. 
  4. The window adjusts the bounds of the view controller’s view. This causes each view in the view hierarchy to be resized based on its autoresizing mask. 
  5. The window calls the view controller’s didRotateFromInterfaceOrientation: method.Container view controllers forward this message to the currently displayed custom view controller. This marks the end of the rotation process. You can use this method to show views, change the layout of views, or make other changes to your application.




3. Responding to Orientation Changes in Two Steps



 


Creating an Alternate Landscape Interface



1. Using two view controllers is simpler and more efficient than making major changes to your view hierarchy each time the orientation changes. It allows each view controller to focus on the presentation of data in one orientation and to manage things accordingly. It also eliminates the need to litter your view controller code with conditional checks for the current orientation.

2. In order to support an alternate landscape interface, you have to do the following:

  • Implement two view controller objects:
    • One should present a portrait-only interface.
    • One should present a landscape-only interface.

@implementation PortraitViewController
- (id)init
{
   self = [super initWithNibName:@"PortraitView" bundle:nil];
   if (self)
   {
       isShowingLandscapeView = NO;
       self.landscapeViewController = [[[LandscapeViewController alloc]
                            initWithNibName:@"LandscapeView" bundle:nil] autorelease];
 
       [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
       [[NSNotificationCenter defaultCenter] addObserver:self
                                 selector:@selector(orientationChanged:)
                                 name:UIDeviceOrientationDidChangeNotification
                                 object:nil];
   }
   return self;
}
 
- (void)orientationChanged:(NSNotification *)notification
{
    UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
    if (UIDeviceOrientationIsLandscape(deviceOrientation) &&
        !isShowingLandscapeView)
    {
        [self presentModalViewController:self.landscapeViewController
                                animated:YES];
        isShowingLandscapeView = YES;
    }
    else if (UIDeviceOrientationIsPortrait(deviceOrientation) &&
             isShowingLandscapeView)
    {
        [self dismissModalViewControllerAnimated:YES];
        isShowingLandscapeView = NO;
    }
}


Tips for Implementing Your Rotation Code

  • Disable event delivery temporarily during rotations. Disabling event delivery for your views prevents unwanted code from executing while an orientation change is in progress.
  • Store the visible map region. If your application contains a map view, save the visible map region value prior to the beginning of rotations. When the rotations finish, use the saved value as needed to ensure that the displayed region is approximately the same as before.
  • For complex view hierarchies, replace your views with a snapshot image. If animating large numbers of views is causing performance issues, temporarily replace those views with an image view containing an image of the views instead. Once the rotations are complete, reinstall your views and remove the image view.
  • Reload the contents of any visible tables after a rotation.Forcing a reload operation when the rotations are finished ensures that any new table rows exposed are filled appropriately.
  • Use rotation notifications to update your application’s state information. If your application uses the current orientation to determine how to present content, use the rotation methods of your view controller (or the corresponding device orientation notifications) to note those changes and make any necessary adjustments.



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值