视频课程:http://code4app.com/course/28-2957-3219
iOS开发之视图控制器(UIViewController): http://liuzhichao.com/p/1408.html
视图控制器应该在MVC设计模式中扮演控制层(C)的角色,UIViewController的职责对内管理与之关联的View,对外跟其他UIViewController通信和协调。一个视图控制器管理一个视图(它可以有子视图),其view属性指向它所管理的视图。
UIViewController是所有视图控制器的父类。
IOS提供了很多内置的视图控制器类,以支持标准的用户界面部分。比如导航控制器(UINavigationController),标签控制器(UITabBarController),表视图控制器(UITabViewController)等。
不要直接把UIView添加到UIWindow上,而是添加一个UIViewController
创建ViewController
现在有一个RootViewController类,接着编辑它的代码。一个视图控制器负责获得或创建它自己的视图。如果视图控制器手动创建它的视图,必须重载UIViewController类的loadView方法。下面给视图设置一个颜色,放一个“Hello World!”标签在这个视图中。
@interface RootViewController () @end @implementation RootViewController -(void) loadView{ // applicationFrame是整个可见区域,不包括状态栏 UIView* view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]]; //设置view的颜色 view.backgroundColor = [UIColor greenColor]; //添加一个标签 UILabel* label = [[UILabel alloc] init]; label.text=@"Hello World!"; //自适应大小 [label sizeToFit]; //居中 label.center = CGPointMake(CGRectGetMidX(view.bounds), CGRectGetMidY(view.bounds)); //添加到view [view addSubview:label]; //设置self.view = view这样视图控制器就可以管理这个视图了,如果实现了loadView那么就必须设置self.view self.view = view; } ... @end
@property (strong, nonatomic) RootViewController *rootViewController;在应用程序委托的实现代码中,我们导入”RootViewController.h”,在应用程序委托的application: didFinishLaunchingWithOptions方法中创建新的视图控制器,并把视图放到界面中。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. self.window.backgroundColor = [UIColor whiteColor]; //创建视图控制器 RootViewController* theRVC = [[RootViewController alloc]init]; self.rootViewController = theRVC; //不仅要创建视图,还必须把视图放到界面中 [self.window addSubview:self.rootViewController.view]; [self.window makeKeyAndVisible]; return YES; }
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. self.window.backgroundColor = [UIColor whiteColor]; //创建视图控制器 RootViewController* theRVC = [[RootViewController alloc]init]; // self.rootViewController = theRVC; //不仅要创建视图,还必须把视图放到界面中 //[self.window addSubview:self.rootViewController.view]; //这行代码与上面注释掉的两行代码的效果是一样的。 self.window.rootViewController = theRVC; [self.window makeKeyAndVisible]; return YES; }
UIViewController* rootController = [[[UIApplication sharedApplication] keyWindow] rootViewController];
使用nib文件
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. self.window.backgroundColor = [UIColor whiteColor]; //使用nib文件创建视图控制器 RootViewController* theRVC = [[RootViewController alloc]initWithNibName:@"View" bundle:nil]; self.window.rootViewController = theRVC; [self.window makeKeyAndVisible]; return YES; }
UIViewController的初始化
程序请求controller的view
如果view在内存中,则直接加载。相反,如果不存在,则UIViewController调用loadView方法
loadView方法执行如下操作:
如果你重载了这个方法,则必须创建必要的view并且将一个非nil值传给UIViewController的view属性。
如果你没有重载这个函数,UIViewController会默认使用UIViewController的nibName和nibBundle属性尝试从nib文件加载view。如果没有找到nib文件,则ViewController会通过以下两个步骤找到与其关联的nib。
A 如果类名包含Controller,例如ViewController的类名是MyViewController,则查找是否存在MyView.nib;
B 找跟ViewController类名一样的文件,例如MyViewController,则查找是否存在MyViewController.nib。
如果没有可用的nib文件,那么它创建一个空的UIView作为它的view。
UIViewController调用viewDidLoad来执行一些加载时任务。
当需要显示或者访问view属性时,view没有创建的话,VC就会调用loadView方法,在这个时候会创建一个view并将其赋给VC.view属性。紧接着就会调用VC的viewDidLoad方法,这个时候VC.view保证是有值的,可以做进一步的初始化操作,例如添加一些subview。注意:定制VC时,如果覆盖loadView方法,不需要调用[super loadView]方法。
UIViewController卸载View的步骤.
对于与之关联的View,UIViewController总是在需要的时候才加载视图,并在不需要的时候卸载视图,所以也同时担当了管理应用资源的责任。理解UIViewController的生命周期(LifeCycle),能够有效地管理应用资源。Controller的view最好在需要显示时再去加载,并且在系统发出内存警告时释放比必要的view及相关的数据对象。UIViewController卸载View的步骤如下:
程序收到内存警告
每个UIViewController调用didReceiveMemoryWarning, 默认会安全地释放掉view
如果UIViewController释放掉了它的view,它会调用viewDidUnload。可以重载这个方法来进行额外的清理工作。
我们在viewDidUnload和dealloc方法应该把该清理的置为nil;
注意,在ios6.0中viewWillUnload和viewDidUnload被弃用了。在内存报警的时候调用didReceiveMemoryWarning。
几个主要的方法:
loadview 当你手动创建视图的是偶,需要这个方法。如果你使用nib或者storyboards,会直接从这些文件加载view。
自定义一些属性和方法 创建一个属性来保持这个方法,需要的时候去调用。
viewDidLoad 分配或加载view中要显示的数据,一般是加载网络请求的数据。
didReceiveMemoryWarning 在ios6.0中,使用该方法来释放对象的引用。一般是内存警告的时候,或者大量的图片数据。
viewDidUnload 在ios6之前使用该方法是否对象的引用
dealloc 重载该方法,执行最后的清理操作。注意,属性会自动释放,不需要手动释放。
要注意的有:
1,6.0用didReceiveMemoryWarning来处理内存紧张的问题
2,self.view不要乱调用,相当于getter方法,尤其是在做内存清理之后,发现nil后会重新调用loadview那一套初始化方法。
3,创建视图控制器时,最好不要在初始化方法中,调用与视图相关的操作。
4,不同版本之间可以方法调用可以通过[self respondsToSelector:@selector(xxxxx)]这种类反射机制来判断,也可以通过读取系统的版本号
([UIDevice currentDevice].systemVersion floatValue] < 6.0)判断。