UIViewController视图控制器
重要知识
视图控制器通常用来管理一个视图,其View属性指向它所管理的视图,这个视图通常被称为根视图
视图控制器并不能显示,具体显示的只是它所管理的视图
作用:创建管理视图;管理视图上显示的数据;设备方向变化,调整视图大小以适应屏幕;负责视图和模型之间的数据及请求的传递
子类:UINavigationController(导航控制器),UITabBarController(标签控制器)
视图控制器的创建
RootViewController *viewController = [[RootViewController alloc] init];
self.window.rootViewController = viewController; //设置窗口的根视图
ViewController的生命周期及其加载View的步骤
ViewController的初始化:从Storyboards中加载的时候,会调用initWithCode,如果不存在则调用init。之后对里面的每个对象调用awakeFromNib方法。从内存中alloc出来的情况下,调init方法。
ViewController查找与其关联的view,其顺序是:
先判断子类是否重写了loadView,如果有直接调用。之后调viewDidLoad完成View的加载。
如果是外部通过调用initWithNibName:bundle指定nib文件名的话,ViewController记载此nib来创建View。
如果initWithNibName:bundle的name参数为nil,则ViewController会通过以下两个步骤找到与其关联的nib。
如果类名包含Controller,例如ViewController的类名是MyViewController,则查找是否存在MyView.nib;
找跟ViewController类名一样的文件,例如MyViewController,则查找是否存在MyViewController.nib。
如果子类没有重写的loadView,则ViewController会从StroyBoards中找或者调用其默认的loadView,默认的loadView返回一个空白的UIView对象。
注意第一步,ViewController是判断子类是否重写了loadView,而不是判断调用子类的loadView之后ViewController的View是否为空。就是说,如果子类重写了loadView的话,不管子类在loadView里面能否获取到View,ViewController都会直接调viewDidLoad完成View的加载。
ViewController的卸载View的步骤:
系统发出警告或者ViewController本身调用导致didReceiveMemoryWarning被调用
调用viewWillUnload之后释放View
调用viewDidUnload
视图控制器的生命周期
模态视图(视图控制器的切换)
模态视图作用:通常用于弹出临时的出窗口,如登录页面
模态视图原理:先将原先控制器的视图,从窗口移除,然后将第二个控制器的视图加到窗口上。
模态视图的弹出与销毁
//模态视图的弹出
//使用模态视图的方式,将vcRegist控制器的视图弹出,但self对象并未被销毁,只是将self的view从superView中//移除
RegisterViewController *vcRegist = [[RegisterViewController alloc] init];
self.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self presentViewController:vcRegist animated:YES completion:nil];
//模态视图的销毁,
//从superView中移除self.view,并且销毁self(视图控制器)对象,销毁后显示(原弹出self的view)的视图控制器//的视图
self.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self dismissViewControllerAnimated:YES completion:NULL];
导航控制器(UINavigationController)
介绍
有多个view时,可以用一个大的view却管理1个或者多个小view,控制器也是如此,用1个控制器去管理其他多个控制器
为了便于管理控制器,iOS提供了2个比较特殊的控制器。UINavigationController(导航控制器)与UITabBarController(标签控制器)
导航控制器属于容器类的控制器,可以管理很多子控制器,通常用它来控制自控制器之间的切换
导航控制器并不作显示,实际显示的是导航控制器所控制的自控制器的视图
特性
UINavigationController用于构建分层应用程序,管理多个视图换入和换出,自身提供视图切换动画效果。
UINavigationController继承自UIViewController
UINavigationController通过栈的方式管理控制器的切换,控制入栈和出栈,来展示各个视图控制器
导航控制器包含:NavigationBar(导航栏),内容视图
UINavigationController始终显示栈顶控制器的view
UINavigationController的viewControllers属性存储了栈中的所有被管理的控制器
被隐藏的工具栏
先设置nav.toolbarHidden = NO;后工具栏才会显示(nav为UINavigationController对象)
toolbarItems属性,可以为工具栏添加UIBarButtonItem类型的按钮
弹簧按钮
UIBarButtonSystemItemFlexibleSpace 将两边的元素(按钮)挤到最边上
UIBarButtonSystemItemFlexedSpace 空格站位按钮,可以设置宽度
子控制器的切换
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated;//进入下一个视图控制器
- (nullable UIViewController *)popViewControllerAnimated:(BOOL)animated;//返回上一个视图控制器
- (nullable NSArray<__kindof UIViewController *> *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated;//返回到指定的视图控制器
- (nullable NSArray<__kindof UIViewController *> *)popToRootViewControllerAnimated:(BOOL)animated;//返回到根视图控制器
导航栏
特性
每个导航控制器只有一个导航栏(UINavigationBar)
导航控制器的每个子控制器都对应了一个导航项(UINavigationItem)
iOS7以后导航栏和状态栏发生了明显的变化,导航栏和状态栏变为了半透明,并且导航栏默认情况下与状态栏交织在一起。iOS7以前导航栏高度为44点,iOS7以后由于样式的改变高度变为64点
导航栏(UINavigationBar)父类:UIView
在UINavigationController类中有UINavigationBar类型的属性navigationBar
在下列代码中navCtrl为UINavigationController的对象
常用属性
@property(null_resettable, NOnatomic,strong) UIColor *tintColor; //按钮字体颜色
@property(nullable, NOnatomic,strong) UIColor *barTintColor; //设置导航栏背景颜色
@property(NOnatomic,assign) UIBarStyle barStyle;//导航栏样式。UIBarStyleBlack黑色半透明,会影响状态栏的颜色
@property(nullable,NOnatomic,weak) id<UINavigationBarDelegate> delegate; //委托
@property(nullable,NOnatomic,copy) NSDictionary<NSString *,id> *titleTextAttributes; //设置导航栏中标题的颜色
navCtrl.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName:[UIColor whiteColor]};
常用方法
- (void)setBackgroundImage:(nullable UIImage *)backgroundImage forBarMetrics:(UIBarMetrics)barMetrics;//设置在UIBarMetrics状态下的背景图片
导航项
特征
在UINavigationController类中UINavigationItem类型的属性名:NavigationItem
导航项的归属关系
常用属性
title 自身ViewController的标题
titleView 自定义的view
prompt 二级标题
leftBarButtonItem、rightBarButtonItem、backBarButtonItem分别设置在导航栏上显示的左、右、返回按钮。类型为UIButtonItem UIButtonItem父类:UIBarItem
self.navigationItem.leftBarButtonItem.customView.hidden = YES 隐藏左边按钮
设置导航栏上的按钮样式
系统提供的方式,只能设置左、右按钮
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithBarButtonSystemItem];
UIBarButtonSystemItemDone target:self action:@selector(test)];
self.navigationItem.leftBarButtonItem = item;
系统提供的方式,但增加了设置按钮标题,可设置左、右、返回按钮
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithTitle:@"Tens" style:[UIBarButtonItemStyleDone target:self action:@selector(test)];
self.navigationItem.leftBarButtonItem = item;
可设置按钮图片,只是保留了图片的形状,颜色被设置为系统颜色,可设置左、右、返回按钮
UIBarButtonItem *item = [[UIBarButton alloc] initWithImage:[UIImage imageNamed:@"test.png"] style:UIBarButtonItemStyleDone target:nil action:nil];
自定义按钮,只可设置左、右按钮
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(0,0,30,30);
btn.setImage: [[UIImage imageNamed:@"test.png"] forState: UIControlStateNOrmal];
[btn addTarget: self action: @selector(totest:) forControlEvents: UIControlEventTochUpInSide];
UIBarButtonItem *btnBarRight = [[UIBarButtonItem alloc] initWithCustomView:btn];
self.navigationItem.rightBarButtonItem = btnBarRight;
标签控制器
特征
UITabBarController是UIViewController的子类
UITabBarController是用一种容器类的控制器,用于管理其他的子控制器
UITabBarController所管理的子控制器不同与导航控制器,UITabBarController的子控制器的平行关系
UITabBarController通常作为整个程序的rootViewController
标签控制器并不做显示,实际显示的是标签控制器所控制的子控制器的视图
使用步骤
初始化UITabBarController
创建若干个子控制器,放入到数组中
通过UITabBarController的ViewControllers属性将要显示的所有子控制器添加到UITabBarController中
将UITabBarController设置为窗口的根控制器
创建方式,ctrl1/ctrl2/ctrl3为UIViewController对象
UITabBarController *tabBar = [[UITabBarController alloc] init];
tabBar.viewControllers = @[ctrl1, ctrl2, ctrl3];
self.window.rootViewController = tabBar;
标签栏(UITabBar),父类:UIView
特征
UITabBarController会提供一个UITabBar(标签栏)
UITabBar的高度为49
当我们给UITabBarController设置子控制器后,系统会为我们自动在UITabBar上创建对应数量的UITabBarItem,用于子控制器的切换
iOS7以后UITabBar默认为半透明
UITabBarController只有一个TabBar(标签栏)
每个子控制器对应一个UITabBarItem,但标签栏上最多显示5个UITabBarItem,如果超过5个最后会以更多的形式显示
常用属性
tintColor 文字、图片的选中颜色
barTintColor 标签栏的背景颜色
backgroundImage 设置标签栏的背景图片
selectionIndicatorImage 设置选中的图片
标签栏元素(UIBarItem),标签栏元素属性名称:tabBarItem
常用属性
selectedImage 被选中后的图片
badgeValue 显示在图标右上角的文本
常用属性
initWithTitle: image: tag: 初始化标签栏元素标题、图标、tag值
initWithTitle: image: selectedImage: 初始化标签栏元素标题、图标、被选中的图标
经验
实现导航控制器push后,影藏TabBar;返回时,显示TabBar。背景:导航控制器是标签控制器的成员,标签控制器是根控制器。解决方案如下:
TabBar嵌套Navigation
self.hidesBottomBarWhenPushed = YES; 设置隐藏时,设置当前及push后的vc隐藏,但已在当前不应藏,以后会隐藏
HomeVC2 *vcHome2 = [[HomeVC2 alloc] init];
[self.navigationController pushViewController: vcHome2 animated:YES];
self.hide.BottomBarWhenPushed = NO; 当设置显示,谁去设置谁才显示,只能设置自己显示
设置TabBarController的TabBar
在tochesBegan事件处理方法中:self.navigationController.tabBarController.tabBar.hidden = YES;
在viewWillAppear事件处理方法中:self.navigationController.tabBarController.tabBar.hidden = NO;
同①相似
HomeVC2 *vcHome2 = [[HomeVC2 alloc] init];
vcHome2.hidesBottomBarWhenPushed = YES;
设置vcHome2 控制器及push以后的标签栏隐藏
[self.navigationController pushViewController:vcHome2 animated:YES];