一、导航控制器基本使用
1.创建一个空项目,创建导航控制器nav,设置导航控制器为Window的根控制器
2.新建3个控制器类管理这3个View(勾上also create xib),在xib中添加一个标签用来注明是第几个控制器,添加一个按钮用来跳转到下一个控制器
3.创建第一个控制器并添加到导航控制器中
[nav pushViewController:one animated:YES];
4.监听用来跳转到第二个的按钮并实现方法
-(IBAction)jump2Two:(id)sender{ //1.创建第二个控制器 //2.将第二个控制器添加到导航控制器中 //只要当前控制器是导航控制器的子控制器,就可以通过该属性直接获取到当前控制器所在的导航控制器 [self.navigationController pushViewController:two animated:YES]; }
5.监听第二个子控制器上的跳转到第三个的按钮并实现该方法。
-(IBAction)jump2Three:(id)sender { //1.创建第三个控制器 //2.将第三个控制器添加到导航控制器中 [self.navigationController pushViewController:three animated:YES]; }
二、导航控制器的管理
导航控制器是通过栈的形式来管理子控制器的(先进后出类似羽毛球桶)
导航控制器的view结构
====>
创建One控制器(被放到导航控制器的栈中)-->自动创建One控制器的View并放到导航控制器的View之上。
再创建Two控制器(被放到导航控制器的栈中)-->自动创建Two控制器的View并将One控制器的View推开,所以显示的是Two控制器的View,
注意:此时One的View并没有销毁
=====>
再创建Three控制器(被放到导航控制器的栈中)-->自动创建Three控制器的View并将Two控制器的View推开,所以显示的是Three控制器的View,注意:此时One的View和Two的View并没有销毁
PS:显示在导航控制器上的view永远是栈顶控制器的view
当点击back时,就会将Three控制器从导航控制器的栈中移除并销毁,同时Three控制器的View也被销毁,此时栈顶控制器由Three控制器变为Two控制器,所以现在屏幕上显示的是Two控制器的View,
再点击back时,就会将Two控制器从导航控制器的栈中移除并销毁,同时Two控制器的View也被销毁,此时栈顶控制器由Two控制器变为One控制器,所以现在屏幕上显示的是One控制器的View
//导航控制器的栈 nav.viewControllers;==nav.childViewControllers; *往栈内添加子控制器的三种方式 //第一种 [nav pushViewController:one animated:YES]; //第二种 [nav addChildViewController:one]; //第三种:给导航控制器的栈直接赋值(不能使用childViewControllers[只读]) nav.viewControllers = @[one]; //第四种(最常用的方式) UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:one]; //获取栈顶控制器 nav.topViewController;
*功能实现:在第三个控制器View上添加按钮,点击后回到第二个控制器View
来到第三个控制器的xib,在上面添加一个按钮,监听点击,实现方法
-(IBAction)back2Two:(id)sender { //移除当前栈顶的控制器 [self.navigationcontroller popViewControllerAnimated:YES]; }
*功能实现:在第三个控制器View上添加按钮,点击后回到第一个控制器View
来到第三个控制器的xib,在上面添加一个按钮,监听点击,实现方法
-(IBAction)back2Root:(id)sender { //移除除了栈底控制器之外的所有控制器 [self.navigationcontroller popToRootControllerAnimated:YES]; }
知识扩展:
//只要传入栈中的某一个控制器,就会跳转到指定控制器 [self.navigationcontroller popToViewController:XXX Animated:YES];
***在导航条上添加内容***
一个导航控制器只有一个导航条,即所有的子控制器共用同一个导航条。导航条上显示的内容和栈顶控制器有关,所以导航条上显示什么内容由栈顶控制器控制。
注意:导航条显示内容的特例:导航条上的返回按钮的文字由上一个控制器决定
来到第一个控制器
-(void)viewDidLoad { [super viewDidLoad]; //控制当前控制器对应的导航条显示的内容 self.navigationItem.title = @"第一个控制器"; //给导航条添加一个按钮(right同理) self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCamera target:nil action:nil]; //修改返回按钮显示的内容(在第一个控制器设置,在第二个控制器view显示) self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@”返回“ style:UIBarButtonItemStylePlain target:nil action:nil]; }
技巧:以后要打印什么的时候在applicationDidBecomeActive:方法(已经可以和用户交互)里打印,而不是在didFinishLaunchingWithOptions:方法中打印
三、导航控制器storyboard
1.来到storyboard,删除默认View,添加一个导航控制器,将默认的根控制器删除
2.拖一个View Controller,将其设置为导航控制器的根控制器
3.再拖一个View Controller,在根控制器上添加一个按钮,以这个按钮为起点连一个push型Segue到刚拖的View Controller上。
4.再重复一次第三步。
5.点击导航条,即可修改标题,返回键等内容。
storyboard弊端:在第三个View上添加一个按钮,点击后回到第二个View。这个功能不能用storyboard实现。只能用代码实现
1>自定义一个类来管理第三个View,并将storyboard的第三个View的Class设置为这个自定义类
2>监听"返回第二个控制器"的按钮,并实现方法
-(IBAction)back2Two:(id)sender { [self.navigationController PopViewControllerAnimated:YES]; }
四、控制器的生命周期
//当控制器的view加载完毕就调用 -(void)viewDidLoad { [super viewDidLoad]; } //控制器的view即将显示的时候调用 -(void)viewWillAppear:(BOOL)animated { [super viewWillAppear:YES]; } //控制器的view完全显示的时候调用 -(void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; } //控制器的view即将消失的时候调用 -(void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; } //控制器的view完全消失的时候调用 -(void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; } //上面的方法没什么技术含量,下面的方法面试中会问到(虽然已经过时) /* //控制器的view即将销毁的时候调用 -(void)viewWillUnload { [super viewWillUnload]; } //控制器的view完全销毁的时候调用 -(void)viewDidUnload { [super viewDidUnload]; //清空不需要的属性 self.foods = nil; } //接收到内存警告的时候调用 -(void)didReceiveMemoryWarning { //按照父类的处理方式去处理内存警告 [super didReceiveMemoryWarning]; } */
系统是如何处理内存警告的?
Q:系统如何判断View是否能销毁?
A:看你这个View是否在Window上。
上述方法其实是一个循环