导航控制器(Navigation Controller)是什么?
和表视图(Table View)一样,导航控制器是另一个UI控件,在iOS App中经常看到。它为分层内容提供了向下导航的界面。我们看看内置的Photos App、YouTube 和通讯录(Contacts)。这些App都使用了导航控制器显示分层的内容。通常表视图和导航控制器在多个App中同时存在,当然,这并不意味着你必须同时使用它们。
1.Storyboards 预览
Storyboard 是 Xcode 4.2 发布时提供的一项新功能。它提供了一个全新的方式,供iOS开发人员创建和设计用户界面。在引入Storyboard 之前,对于初学者而言非常困难创建导航(和tab)界面。每一个界面存放在一个独立的nib文件中,然后你必须编写代码连接所有的界面,并且描述导航如何工作。
通过使用Storyboard,所有屏幕保存在一个单一文件中,这样你就可以预览app的可视化展示,以及屏幕是如何链接的。Xcode提供了内置的编辑器来设计Storyboards.你可以简单点击来定义不同屏幕之间的切换(称为Segues - 联线,代表两个场景Scene之间的过度转换),但这也不是说你不必为用户界面编写代码,Storyboards 显著简化了你需要编写的代码量。下图显示Xcode中Storyboards 的样子:
2.场景(Scene) 和联线(Segues)
在使用Storyboards 时,一定会遇到场景(Scene)和联线(Segues)两个术语。在一个Storyboard中,场景指一个单一的视图控制器和它的视图。每一个场景都有一个场景坞(Dock),主要用来在视图控制器和视图之间,建立方法和Outlet的连接。
联线(Segue)位于两个场景之间,管理两个场景之间的过度,其中Push和Modal是两个常见的过度类型。
3.在Storyboards 中创建导航控制器
现在着手创建我们自己的 Storyboards.我们将创建一个简单的App,其中同时用到UITableView 和 UINavigationController.
我们使用表现图显示菜单列表。在用户选择任何菜单时,App导航到另外一个画面,显示更详细的信息。
首先,启动Xcode,并使用Single View application 模板创建一个新的项目。
输入如下选项:
Product Name : RecipeBook
Company identifier : com.appcoda
Class Prefix : RecipeBook
Device Family: : iPhone
确保勾选Use Storyboards 选项。
选用 Use Automatic Reference Counting
点击继续保存项目
这里与前面项目不同的一点,.xib 文件(interface builder) 替换为MainStoryboard.stroyboard 文件了。
默认情况下,Xcode 创建一个标准的视图控制器。我们将使用导航控制器(Navigation Controller)控制画面的导航。首先更改视图控制器(View Controller)为导航控制器,选择Editor菜单 / Embed in 子菜单, 接着选择Navigation Controller,
Xcode 自动嵌入RecipeBook 视图控制器到导航控制器中,项目的画面如下图所示:
现在我们运行App 看看效果,点击Run按钮,你将看到一个空白的视图,并且添加了一个导航条。这表明你已经成功嵌入了RecipeBook 视图控制器到导航控制器中。
4.添加表视图及其数据
接着,我们将添加表视图显示菜谱。从对象库(Object Library)选择Table View,并拖拉到Recipe Book View Controller 中。
需要注意的是:当编辑器是最小化时,你不能拖动控件;如果你不能拖动Table View 到视图控制器,最大化编辑器,在尝试一次。
接下来,我们需要编写代码填充数据(如菜谱)。在项目导航中,选择Recipe BookViewController.h 文件,在UIViewController之后,添加<UIT ableViewDelegate,UITableViewDataSource>,代码如下所示:
#import <UIKit/UIKit.h>
@interface RecipeBookViewController : UIViewController<UITableViewDelegate,UITableViewDataSource>
@end
@implementation RecipeBookViewController
{
NSArray *recipes;
}
- (void)viewDidLoad
{
[super viewDidLoad];
//Initialize table data
recipes = [NSArray arrayWithObjects:@"Egg Benedict",@"Mushroom Risotto",@"Full Breakfast",@"Hamburger",@"Ham and Egg sandwith",@"Creme Brelee",@"White Chcolate Dount",@"Starbucks Coffee",@"Vegetable Curry",@"Instant Noodle with Egg",@"Noodle with BBQ Pork",@"Japanese Noodle with Pork",@"Green Tea",@"Thai Shrimp Cake",@"Angry Birds Cake",@"Ham and Cheese Panini",nil];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [recipes count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = @"RecipeCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [recipes objectAtIndex:indexPath.row];
return cell;
}
@end
本例子目的只是演示如何实现导航控制器。我们尽量让详细视图简单一点,仅添加一个Label显示菜单名称。
从对象库中拖拉Label控件,并放置在视图的中心位置。你可以更改字体大小或类型,让Label更好看一些。
接着,我们添加一个联线(Segue),连接原型单元格和新添加的视图控制器。添加一个联线对象非常简单。按住Control键,点击原型单元格,并拖拉到视图单元格。
释放按钮,弹出窗口中显示3种类型的联线,分别是P ush、Modal和Custom。
之前解释过,联线定义了两个场景之间的过度类型,对于标准的导航,我们使用Push,一旦选择,Xcode自动使用Push联线连接两个场景。
现在再次运行App,在你选择任一菜单时,App将显示详细视图控制器。尽管详细视图控制仅仅显示一个标签,但是我们已经让导航功能工作正常了。