文档章节

iOS开发17:使用Navigation Controller切换视图

双子座
 双子座
发布于 2012/04/10 14:30
字数 1683
阅读 28950
收藏 23

之前有两篇文章讲了使用Tool Bar和Tab Bar切换视图。其实,切换视图并不复杂,无非就是View Controller的切换。

这篇文章介绍使用UINavigationController切换视图。这个Navigation Controller功能强大,主要用来切换多级的视图。可以将Navigation Controller理解成一个栈,这个栈中可以存放很多View Controller。在这个栈创建的时候,我们先给它添加一个View Controller,称为Root View Controller,它放在栈底,代表的是刚加载程序的时候显示的视图。当用户新选择了一个想要显示的视图时,那个新的View Controller入栈,它所控制的视图就会显示出来。这个新的View Controller通常称作Sub Controller。

进入一个新的视图后,左上方会出现一个按钮,叫做Navigation Button,它就像浏览器的后退按钮一样,点击此按钮,当前的View Controller出栈,之前的View就会显示。

这种设计模式使得开发变得简单,我们只需知道每一个View Controller的Sub Controller就好了。

我们这次要做的小例子运行如下图:

     

左边的图片是刚运行时显示的效果,它是一个表格,表格中的每一行代表不通过的View Controller。注意到每一行的右边有一个图标,叫做Disclosure Indicator,它用来告诉用户单击这一行会进入另一个视图。当点击某行,就进入中间图片显示的视图。中间图片中,左上角的按钮就是Navigation Button。中间的图片中,每一行右边有一个按钮,叫做Detail Disclosure Button,它不仅仅是一个图标,实际上它是一个控件,用户点击它会进入该行的详细说明。点击某行的Detail Disclosure Button,进入相应的视图,如右边的图片。

为了更好地理解Navigation Controller的原理,我们从Empty Application开始我们的小例子。

1、运行Xcode 4.2,新建一个Empty Application,名称为:Navigation Controller Test:

2、创建一个View Controller,作为Root View Controller:依次选择File——New——New File,在弹出的窗口,左边选择iOS下的Cocoa Touch,右边选择UIViewController subclass:

单击Next,在新窗口输入名称为RootViewController,sub of选择UItableViewController:

之后选好位置,完成创建。

3、打开AppDelegate.h,向其中添加属性:

@property (strong, nonatomic) UINavigationController *navController;

然后打开AppDelegate.m,在@implementation之前添加代码:

#import "RootViewController.h"

在@synthesize window = _window;之后添加代码:

@synthesize navController;

#pragma mark - 
#pragma mark Application lifecycle

在didFinishLaunchingWithOptions方法中添加代码:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    
    RootViewController *root = [[RootViewController alloc] initWithStyle:UITableViewStylePlain]; 
    self.navController = [[UINavigationController alloc] initWithRootViewController:root]; 
    [self.window addSubview:navController.view];
    
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
}

4、我们先要明确,Root View Controller中是一个表格,它的每一行对应一个Sub View Controller。

打开RootViewController.h,添加属性:

@property (strong, nonatomic) NSArray *controllerList;

打开RootViewController.m,在@implementation之后添加代码:

@synthesize controllerList;

在viewDidLoad中[super viewDidLoad];之后添加代码:

self.title = @"分类"; 
NSMutableArray *array = [[NSMutableArray alloc] init]; 
self.controllerList = array;

在ViewDidUnload方法中添加代码:

self.controllerList = nil;

找到numberOfSectionsInTableView方法,修改其返回值为1。

找到numberOfRowsInSection:方法,修改代码为:

return [controllerList count];

找到cellForRowAtIndexPath方法,修改其中代码如下:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *RootTableViewCell = @"RootTableViewCell"; 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: RootTableViewCell]; 
    if (cell == nil) { 
        cell = [[UITableViewCell alloc] 
                initWithStyle:UITableViewCellStyleDefault
                reuseIdentifier: RootTableViewCell]; 
    } 
    NSUInteger row = [indexPath row]; 
    UITableViewController *controller = [controllerList objectAtIndex:row]; 
    //这里设置每一行显示的文本为所对应的View Controller的标题
    cell.textLabel.text = controller.title;
    //accessoryType就表示每行右边的图标
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 
    return cell; 
}

找到didSelectRowAtIndexPath:方法,修改其中代码如下:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSUInteger row = [indexPath row]; 
    UITableViewController *nextController = [self.controllerList objectAtIndex:row]; 
    [self.navigationController pushViewController:nextController animated:YES]; 
}

5、现在为止,我们还看不到什么效果,那是因为controllerList这个数组现在是空的。

接下来我们创建一个Table View Controller,用于显示电影列表。建立的方法同建立RootViewController一样,名称为:MovieViewController。

之后再创建一个View Controller,名称为MovieDetailViewController,用于显示电影的详细信息,这次我们要选中include xib file…选项,并且Subof选项为UIViewController:

6、打开MovieDetailViewController.xib,拖一个Label到中间,并拉长。将其映射到MovieDetailViewController.h中,名称为detailLabel:

然后在MovieDetailViewController.h中添加属性:

@property (copy, nonatomic) NSString *message;

打开MovieDetailViewController.m,在@implementation之后添加代码:

@synthesize message;

在viewDidLoad方法后面添加一个方法:

- (void)viewWillAppear:(BOOL)animated { 
    detailLabel.text = message; 
    [super viewWillAppear:animated]; 
}

viewWillAppear这个方法每次视图加载都会执行,而viewDidLoad方法只有在第一次加载时才会执行。

在viewDidUnload方法中添加代码:

self.detailLabel = nil;
self.message = nil;

7、打开MovieViewController.h,向其中添加属性:

@property (strong, nonatomic) NSArray *movieList;

打开MovieViewController.m,在@implementation之前添加代码:

#import "MovieDetailViewController.h"
#import "AppDelegate.h"
@interface MovieViewController () 
@property (strong, nonatomic) MovieDetailViewController *childController; 
@end

在@implementation之后添加代码:

@synthesize movieList;
@synthesize childController;

在viewDidLoad方法中添加代码:

NSArray *array = [[NSArray alloc] initWithObjects:@"肖申克的救赎", @"教父", @"教父:II",
                  @"低俗小说", @"黄金三镖客", @"十二怒汉", @"辛德勒名单",
                  @"蝙蝠侠前传2:黑暗骑士", @"指环王:王者归来", @"飞越疯人院",
                  @"星球大战Ⅴ:帝国反击战", @"搏击俱乐部", @"盗梦空间", @"七武士",
                  @"指环王:护戒使者", @"好家伙", @"星球大战IV:新希望", @"上帝之城",
                  @"卡萨布兰卡", @"黑客帝国", @"西部往事", @"后窗", @"夺宝奇兵",
                  @"沉默的羔羊", @"非常嫌疑犯", @"七宗罪", @"指环王:双塔奇兵", @"阿甘正传",
                  @"惊魂记", @"美好人生", nil];
self.movieList = array;

在ViewDidUnload方法中添加代码:

self.movieList = nil;
self.childController = nil;

找到numberOfSectionsInTableView方法,修改其返回值为1。

找到numberOfRowsInSection:方法,修改代码为:

return [movieList count];

找到cellForRowAtIndexPath方法,修改其中代码如下:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *MovieTableViewCell = @"MovieTableViewCell"; 
    UITableViewCell *cell = [tableView
                             dequeueReusableCellWithIdentifier: MovieTableViewCell]; 
    if (cell == nil) { 
        cell = [[UITableViewCell alloc] 
                initWithStyle:UITableViewCellStyleDefault
                reuseIdentifier: MovieTableViewCell]; 
    } 
    NSUInteger row = [indexPath row]; 
    NSString *movieTitle = [movieList objectAtIndex:row];
    //这里设置每一行显示的文本为所对应的View Controller的标题
    cell.textLabel.text = movieTitle;
    //accessoryType就表示每行右边的图标
    cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton; 
    return cell;
}

修改didSelectRowAtIndexPath方法:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES]; 
}

在@end之前添加方法:

- (void)tableView:(UITableView *)tableView
  accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath { 
    if (childController == nil) { 
        childController = [[MovieDetailViewController alloc]
                           initWithNibName:@"MovieDetailViewController" bundle:nil]; 
    } 
    NSUInteger row = [indexPath row]; 
    NSString *selectedMovie = [movieList objectAtIndex:row]; 
    NSString *detailMessage = [[NSString alloc]
                               initWithFormat:@"你选择了电影:%@.", selectedMovie]; 
    childController.message = detailMessage; 
    childController.title = selectedMovie; 
    [self.navigationController pushViewController:childController animated:YES]; 
}

8、打开RootViewController.m,在@implementation之前添加代码:

#import "MovieViewController.h"

在viewDidLoad方法中self.controllerList = array;之前添加代码:

//电影 
MovieViewController *movieViewController = [[MovieViewController alloc]
                                            initWithStyle:UITableViewStylePlain]; 
movieViewController.title = @"电影";  
[array addObject:movieViewController];

9、运行一下:

     

RootViewController表格中其他选项的实现跟上面是类似的,重复操作比较多,不再讲了。

总的来说,Navigation Controller还是很强大的。使用的时候把它想象成一个栈,用起来就会比较简单。

最终代码:http://www.oschina.net/code/snippet_164134_12787

© 著作权归作者所有

双子座
粉丝 540
博文 78
码字总数 61009
作品 0
南京
程序员
私信 提问
加载中

评论(15)

s
s6060304
三年前的文章,令小弟也能一窺navigationView的強大
謝謝~

ps:ios5之後,在appdelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 裡面要加上 self.window.rootViewController = root; 才能順利執行喔~ =)
在root建好後就加上這行就可以了!
总是搞不懂
总是搞不懂

引用来自“ooo_小妖”的评论

- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath 没有调用到是什么地方问题???

我也遇到这个问题了 朋友 你解决了吗 请赐教下!不胜感激!
双子座
双子座 博主

引用来自“Hxy060799”的评论

谢谢楼主的教程。楼主的很多教程我都有在看,给了很大的帮助,支持一下!

^_^
Hxy060799
Hxy060799
谢谢楼主的教程。楼主的很多教程我都有在看,给了很大的帮助,支持一下!
双子座
双子座 博主

引用来自“傲尔其郎”的评论

引用来自“双子座”的评论

引用来自“傲尔其郎”的评论

楼主有工程代码吗;分享一下吧;

http://www.oschina.net/code/snippet_164134_12787

哥们你好啊,想跟你学习ios开发啊;能加个好友吗;472878981

首先感谢你的信任。其实我iOS很菜的,只是前几个月做过一点iPad项目,现在已经不搞了,我水平有限,教不了你什么。建议你多看看英文书,APress官网上有很多关于iOS的书,都很不错。
傲尔其郎

引用来自“双子座”的评论

引用来自“傲尔其郎”的评论

楼主有工程代码吗;分享一下吧;

http://www.oschina.net/code/snippet_164134_12787

哥们你好啊,想跟你学习ios开发啊;能加个好友吗;472878981
双子座
双子座 博主

引用来自“傲尔其郎”的评论

楼主有工程代码吗;分享一下吧;

http://www.oschina.net/code/snippet_164134_12787
傲尔其郎
楼主有工程代码吗;分享一下吧;
董佳琪
楼主好人!!顶了。
k
kazuko
挺详细的,直接可以创建出来了,能正常运行,没错误。我是新手,为啥这里都显示了视图,但是只有一个xib文件?这个都是代码创建视图了是吗?
真是茅塞顿开啊。。。。thanks 啊
UIView Animations 学习笔记(二)定制动画效果及切换效果

目录 UIView Animations 学习笔记(一)简介及API说明 UIView Animations 学习笔记(二)定制动画效果及切换效果 UIView Animation 学习笔记 应用示例 二、视图切换定制 2.1 基础说明 要创建...

灰大羊
2015/08/12
192
0
TeeChart .NET for iOS图表开发入门教程

去年,TeeChart 为iOS图表开发专门发布了TeeChart NET for iOS(包含在TeeChart Mobile中,TeeChart8.5折进行中),相信很多人都对其感兴趣。慧都为大家制作了TeeChart NET for iOS的入门教程...

裸奔的火腿肠
2014/02/25
75
0
iOS 7开发快速入门随书资料

《iOS 7开发快速入门》全面、系统地介绍了iOS 7开发技术。全书共分3篇17章。 第1篇 包括第1~4章,介绍了iOS 7的新功能、iOS 7的开发工具Xcode 5、第一个iOS 7应用程序的开发、Objective-C语...

请叫我院长
2014/02/19
822
1
【书坊赠书福利——第二期】《iOS 8开发指南》

本周是人邮IT书坊赠书的第二期,第一期参与度极高,微信君在此感谢你们的支持,第一期获奖赠书已全部寄出。 本周赠品 本周,微信君给大家推荐@人民邮电出版社-信息技术分社 刚刚上架的新书《...

生气的散人
2014/09/23
381
0
IOS软件开发视频教程要的来

IPhone开发实战视频教程内容介绍 1.iPhone开发实战视频教程-iOS开发视频教程 介绍了iPhone开发的开发环境iOS SDK,X-Code,Interface Builder,iTunes等;创建项目的基本步骤,项目工程中文件...

三毛钱
2016/07/09
249
3

没有更多内容

加载失败,请刷新页面

加载更多

反编译9.png图片还原

本文链接:https://blog.csdn.net/a1140778530/article/details/10528507 经常反编译apk文件找资源,9.png的文件处理起来很麻烦。 最近使用Ant自动编译打包app时,从别处搜罗来的9.png文件导...

shzwork
16分钟前
4
0
Shell脚本应用 – for、while循环语句

一、for循环语句 在实际工作中,经常会遇到某项任务需要多次执行的情况,而每次执行时仅仅是处理的对象不一样,其他命令相同。例如:根据通讯录中的姓名列表创建系统账号等情况。 当面对各种...

linux-tao
17分钟前
5
0
RPA风潮下企业财务工作模式的变革

RPA(机器人流程自动化)在财务领域的应用,正给企业财务带来前所未有的改变。 前RPA时代,财务领域面临的痛点 在RPA机器人应用之前,企业财务工作进程的推进,主要通过财务人员人工操作或信...

UiBot
22分钟前
5
0
Hive之命令行修改表注释

最近遇到一个需求,在不重建表的情况下,修改表的注释,hive有没有类似关系型数据库的SQL命令来修改呢,找了下,亲测有效,如下List-1 List-1 hive>use your_schemahvie>ALTER TABLE tabl...

克虏伯
22分钟前
5
0
是什么,它的作用是什么

在HTML文档的首部往往会有这么一句话<!DOCTYPE html>,许多时候我们忽视了它的存在,它实际上是一个声明,告诉浏览器用哪种HTML版本的规范来解读HTML文档。 尽管我们不给出这句声明浏览器照样...

前端老手
28分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部