首页 > 代码库 > ios – 视图控制器如何管理视图?

ios – 视图控制器如何管理视图?

移动设备的屏幕有限,所有的东西都需要放到一个单一窗口组成的单一界面显示,在ios中体现为视图切换(在《ios – 视图》中已经说明了视图),当一个视图替换掉另一个视图的时候,会经常使用动画效果,这个任务就是交给视图管理器来完成的。

ios5之后应用程序窗口有一个根视图控制器(rootViewController),当不为rootViewController赋值时,会出现“Application windows are expected to have a root view controller at the end of application launch”警告。

1. 视图控制器的实例化方式

视图控制器的实例化也有几种方式:
第一种: 代码,也是我最喜欢的一种,不是因为它简单,是因为使用代码会使得程序的结构变得清晰简单 更易懂。

[[ViewController alloc] init];[[ViewController alloc]initWithNibName:@"xibName" bundle:nil];

第二种:代理类加载xib

1 . xib文件里面需要一个ViewController,并将xib的 File‘s Owner的Identity inspector中的class设置为应用程序代理类。

2 . 代理类中添加一个ViewController插座变量并连接。

3 . 在application:didFinishLaunchingWithOptions:方法中加载xib文件。

第三种:串联图

2.视图控制器如何创建视图

UIViewController中有loadView这个方法,默认情况下,自己的视图控制器并没有重写这个方法,本人测试过,当第一次访问view这个属性的时候,就会自动调用loadView这个方法,重写这个方法,代码如下:

- (void)loadView{    self.view = [[UIView alloc] init]; }

跟不重写一样的效果,所以本人就猜想UIViewController中loadView这个方法也是如此实现(没有使用xib的情况下),欢迎指正。

3.view的生命周期

UIViewController中声明如下方法:

//加载视图- (void)loadView; //j将要卸载视图- (void)viewWillUnload NS_DEPRECATED_IOS(5_0,6_0);//已经卸载视图- (void)viewDidUnload NS_DEPRECATED_IOS(3_0,6_0); //已经加载- (void)viewDidLoad; //视图将要显示- (void)viewWillAppear:(BOOL)animated;    //视图已经显示- (void)viewDidAppear:(BOOL)animated;     //视图将要隐藏- (void)viewWillDisappear:(BOOL)animated; //视图已经隐藏- (void)viewDidDisappear:(BOOL)animated; //将要调用layoutSubviews- (void)viewWillLayoutSubviews NS_AVAILABLE_IOS(5_0);//已经调用layoutSubviews- (void)viewDidLayoutSubviews NS_AVAILABLE_IOS(5_0);

可以重写这些方法进行生命生命周期的管理。

4.旋转

视图控制器的一个主要任务就是知道如何旋转视图,有两种不同旋转:

抵消旋转

应用的旋转是为了抵消设备方向的旋转,从而应用可以根据用户如何手持设备而正确的显示。抵消旋转的挑战仅仅在于屏幕不是正方形,这意味着,如果应用旋转90度,界面不再适合屏幕,必须做出改变进行抵消。

强制旋转

当某个特定的视图出现在上界面上时应用进行旋转,或者在应用启东时,为了告诉用户需要旋转设备才能正确显示视图。这是很常见的,因为界面是特地的设计的,而屏幕并不是正方形,所以事实上只能显示某一特定的模式(竖屏或横屏)。

为了支持旋转,视图控制器需要做的事就是重写shouldAutorotateToInterfaceOrientation:,传入的参数是当前设备的方向,是如下之一:

UIInterfaceOrientationPortrait  Home健在下方

UIInterfaceOrientationPortraitUpsideDown  Home健在下方

UIInterfaceOrientationLandscapeLeft  Home健在左边

UIInterfaceOrientationLandscapeRight  Home健在右边

返回YES允许所有方向旋转,否则返回NO,如果没有重写这个方法,默认是对UIInterfaceOrientationPortrait  返回YES,而其他方向返回NO的,必须对某些方向返回YES。(没有UIViewController属性可以设置为视图控制器可旋转的方向,只能重写这个方法)。

iOS 5有一个新特性,就是shouldAutorotateToInterfaceOrientation可以动态的实现, 使用attemptRotationToDeviceOrientation这个方法

该方法的使用场景是 interface orientation和device orientation 不一致,但希望通过重新指定 interface orientation 的值,立即实现二者一致;如果这时只是更改了支持的 interface orientation 的值,没有调用attemptRotationToDeviceOrientation,那么下次 device orientation 变化的时候才会实现二者一致,关键点在于能不能立即实现。

举个例子:

假设当前的 interface orientation 只支持 Portrait,如果 device orientation 变成 Landscape,那么 interface orientation 仍然显示 Portrait;

如果这时我们希望 interface orientation 也变成和 device orientation 一致的 Landscape,以iOS 6 为例,需要先将 supportedInterfaceOrientations 的返回值改成Landscape,然后调用 attemptRotationToDeviceOrientation方法,系统会重新询问支持的 interface orientation,已达到立即更改当前 interface orientation 的目的。

旋转事件

可以通过视图控制器的interfaceOrientation属性知道当前界面的方向, UIViewController的子类可以重写下列方法,以便在旋转的前后收到通知:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation

ios – 视图控制器如何管理视图?