2016-11-08 03:06
  1299      0   

页面的切换跳转UINavigationController

daodu
app一般有很多个页面,一个页面会对应一个UIViewController。那怎么控制页面的切换呢?拖线就不讲了!这里介绍一种可以控制页面切换的控制器:导航控制器UINavigationController,就像一个view下面有很多个子view一样,导航控制器会通过添加(push)或删除(pop)其子控制器view,来实现页面的切换,类似于栈。

nav22.png

1. UINavigationController的使用

        先来看看导航控制器是怎么做到界面切换的,之前手动加载界面时将UIViewController设置为window的根控制器就可以显示该页面了。现在我们将UINavigationController作为window的根控制器。通过向NavgationController对象添加子控制器view的方式,显示页面。

屏幕快照 2017-01-19 23.45.16.png

    实例操作: 

    > 设置不从main加载storyboard。在代理里初始化UINavigationController

    > 设置UIWindow的rootViewController为UINavigationController

    > 通过push方法将控制器view添加到导航栈

    _window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    
    // 创建导航控制器的根控制器
    ViewController* rootVc = [[ViewController alloc] init];
    //rootVc.view.backgroundColor = [UIColor greenColor];
    
    // 创建导航控制器
    // 导航控制器也需要有根控制器
    UINavigationController* navVc = [[UINavigationController alloc] initWithRootViewController:rootVc];
    // initWithRootViewController: 调用了push方法.
    // 导航控制器的根控制器就是导航控制器的第一个子控制器

    _window.rootViewController = navVc;
    
    [_window makeKeyAndVisible];

 这里其实就是在viewController中间加了一层NavigationController。顶部会明显的多出一个导航栏,页面的跳转: 上面用ViewController直接定义的导航控制器的根控制器 alloc] init] 后,会默认去加载对应的stroyboard或xib,这里我们建立一个xib对应他,拖拽一个按钮用来跳转到第二个界面, 这里我们需要新建一个viewController来作为目的界面,新建类时勾选Also create XIB file,就可以了。

    

屏幕快照 2017-01-05 10.37.12.png

    下面是跳转相关:

    

屏幕快照 2016-11-09 10.34.38.png

    

屏幕快照 2016-11-09 10.36.31.png

    ViewController.m

@implementation ViewController

- (IBAction)jump2Two:(id)sender {
    NSLog(@"%s", __func__);
    // 导航控制器只显示栈顶控制器的view
    TwoViewController* twoVc = [[TwoViewController alloc] init];
    
    // 只有导航控制器才有跳转功能
    // 只要是导航控制器的子控制器就能拿到导航控制器
    [self.navigationController pushViewController:twoVc animated:YES];
    // 会把push的控制器添加为导航控制器的子控制器
    NSLog(@"%@", self.navigationController.childViewControllers);
}

    点击跳转到第二个界面效果  

屏幕快照 2016-11-09 10.37.57.png

    如果想跳转到一个界面只需要将其控制器push到导航控制器数组里,导航控制器只显示栈顶的控制器

    点击back返回就是相当于pop出栈一次, 可以pop到指定的控制器,子控制器里获取导航控制器数组:

    self.navigationController.childViewControllers

// 返回,出栈
- (IBAction)back2Pre:(id)sender {
    [self.navigationController popViewControllerAnimated:YES];
}

// 回到根控制器, 跳转到指定的控制器
- (IBAction)back2Root:(id)sender {
    //[self.navigationController popToRootViewControllerAnimated:YES];
    
    [self.navigationController popToViewController:self.navigationController.childViewControllers[0] animated:YES];
}

2. addChildViewController与push

        上面有提到,导航控制器是通过数组来控制器页面切换的,但系统的方法是push和pop,类似于入栈出栈,我试了下直接向导航控制器添加子控制器的方式即  [navVc addChildViewController:rootVc],在设置根控制器的时候没问题,但在ViewController里面准备跳转到twoVc就不能使用添加子控制器的方法了,只有用push才能跳转,表面是只是添加了子控制器,但push做的不仅仅做了addChildViewController操作,还加了一些隐藏的处理。多次push同一个控制器会出错。

屏幕快照 2017-01-19 23.05.31.png

3. 导航条内容的设置

    导航条的内容是由栈顶控制器的navigationItem决定,也就是当前显示的界面,一般放在viewDidload中加载

@implementation TwoViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    
    self.navigationItem.title = @"中间内容";
    
    // 添加导航条右边的按钮
    UIBarButtonItem* item = [[UIBarButtonItem alloc] initWithTitle:@"右边" style:UIBarButtonItemStyleDone target:self action:@selector(click)];
    self.navigationItem.rightBarButtonItem = item;
    
    // 添加左边的按钮
    UIImage* image = [UIImage imageNamed:@"navigationbar_friendsearch"];
    image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    // 一张图片时
//  UIBarButtonItem* item2 = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStyleDone target:nil action:nil];
    
    // 一个按钮两张图片
    UIButton* btn = [UIButton buttonWithType:UIButtonTypeCustom];
    [btn setBackgroundImage:image forState:UIControlStateNormal];
    [btn setBackgroundImage:[UIImage imageNamed:@"navigationbar_friendsearch_highlighted"] forState:UIControlStateHighlighted];
    // 如果是自定义按钮要定义尺寸, 导航条上的内容位置由系统决定, 按钮的尺寸自己可以定义
    btn.frame = CGRectMake(100, 0, 35, 35);
    UIBarButtonItem* item2 = [[UIBarButtonItem alloc] initWithCustomView:btn];
    
    self.navigationItem.leftBarButtonItem = item2;
    // 在apple的API中,只要以Item结尾,都是苹果的模型
    // UINavigationItem: 决定导航条的内容(左,中,右)
    // UIBarButtonItem: 决定导航条上按钮的内容
}

- (void)click
{
    NSLog(@"%s", __func__);
}

    显示效果如下:   

屏幕快照 2016-11-09 11.54.57.png


    代码打包:复习0105_Nav.zip


4. 控制器view的生命周期方法

    页面第一次加载时:

    viewDidLoad -> viewWillAppear -> viewWillLayoutSubviews -> viewDidLayoutSubviews -> viewDidAppear

    跳转到其他页面时执行 viewWillDisappear -> viewDidDisappear

    再次回到该界面时 viewWillAppear ->  viewDidAppear 

    屏幕快照 2016-11-09 14.03.49.png

    当出现内存警告时执行 didReceiveMemoryWarning方法,清空一些缓存,一般清空图片,一些没用的数据

    在非ARC环境下常用的方法:

    viewWillUnload、viewDidUnload 控制器view即将/完成销毁


本文根据小码哥视频整理 www.520it.com