文档章节

iOS开发19:Storyboard的简单使用

双子座
 双子座
发布于 2012/04/17 21:00
字数 2175
阅读 63459
收藏 61

之前做的例子,我们经常会用到.xib文件,在其中我们可以进行界面的设计。不过如果想切换视图,我们就得自己写很多代码。自从苹果推出了Storyboard,我们可以在一个编辑区域设计多个视图,并通过可视化的方法进行各个视图之间的切换。如下图:

上图中有两种箭头:左边的箭头表示程序刚开始运行时加载的控制器;右边的称为Segue,这个表示视图之间的切换,或者表示连接Navigation Controller的Root View Controller。

Storyboard功能强大,通过它不仅可以单独设计每一个视图,还能很简单地实现各个视图之间的切换。

接下来的例子主要显示Storyboard的功能,顺便用Storyboard实现了静态表格等功能。为了显示Storyboard的功能,我们从Empty Application开始我们的例子。

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

2、打开AppDelegate.m,找到didFinishLaunchingWithOptions方法,删除其中代码,使得只有return YES;语句。

3、创建一个Storyboard:

在菜单栏依次选择File — New — New File,在弹出的窗口,左边选择iOS组中的User Interface,右边选择Storyboard:

之后单击Next,选择Device Family为iPhone,单击Next,输入名称MainStoryboard,并设好Group:

单击Create,这样就创建了一个Storyboard。

4、配置程序,使得从MainStoryboard启动:

先单击左边带蓝色图标的Storyboard Test,然后选择Summary,接下来在Main Storyboard中选择MainStoryboard:

这样,当运行程序时,就从MainStoryboard加载内容了。

5、单击MainStoryboard.storyboard,会发现编辑区域是空的。拖一个Navigation Controller到编辑区域:

6、选中右边的View Controller,然后按Delete键删除它。之后拖一个Table View Controller到编辑区域:

7、我们将在这个Table View Controller中创建静态表格,不过先要将其设置为左边Navigation Controller的Root Controller:

选中Navigation Controller,按住Control键,向Table View Controller拉线:

松开鼠标后,在弹出菜单选择Relationship - rootViewController:

之后,两个框之间会出现一个连接线,这个就可以称作是Segue。

8、选中Table View Controller中的Table View,之后打开Attribute Inspector,设置其Content属性为Static Cells:

这样你会发现Table View中出现了三行Cell。在上图你可以设置很多熟悉,比如Style、Section数量等。

9、设置行数:

选中Table View Section,在Attribute Inspector中设置其行数为2:

然后选中每一行,设置其Style为Basic:

设置第一行中Label的值为:Date and Time,第二行中的Label为List;之后选中下方的Navigation Item,在Attribute Inspector设置Title为Root View,Back Button为Root:

10、我们实现单击表格中的Date and Time这一行实现页面转换,在新页面显示切换时的时间。

在菜单栏依次选择File — New — New File,在弹出的窗口左边选择iOS中的Cocoa Touch,右边选择UIViewController subclass:

单击Next,输入名称DateAndTimeViewController,但是不要选XIB:

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

11、再次打开MainStoryboard.storyboard,拖一个View Controller到编辑区域,然后选中这个View Controller,打开Identity Inspector,设置class属性为DateAndTimeViewController:

这样,我们就可以向DateAndTimeViewController创建映射了。

12、向新拖入的View Controller添加控件,如下图:

然后将显示为Label的两个标签向DateAndTimeViewController.h中创建映射,名称分别是dateLabel、timeLabel:

13、打开DateAndTimeViewController.m,在ViewDidUnload方法之后添加代码:

//每次切换到这个试图,显示切换时的日期和时间
- (void)viewWillAppear:(BOOL)animated {
    NSDate *now = [NSDate date];
    dateLabel.text = [NSDateFormatter
                      localizedStringFromDate:now
                      dateStyle:NSDateFormatterLongStyle
                      timeStyle:NSDateFormatterNoStyle];
    timeLabel.text = [NSDateFormatter
                      localizedStringFromDate:now
                      dateStyle:NSDateFormatterNoStyle
                      timeStyle:NSDateFormatterLongStyle];
}

14、打开MainStoryboard.storyboard,选中表格的行Date and Time,按住Contrl,向View Controller拉线:

在弹出的菜单选择Push:

这样,Root View Controller与DateAndTimeViewController之间就出现了箭头,运行时当点击表格中的那一行,视图就会切换到DateAndTimeViewController。

15、选中DateAndTimeViewController中的Navigation Item,在Attribute Inspector中设置其Title为Date and Time:

16、运行一下,首先程序将加载静态表格,表格中有两行:Date and Time以及List,单击Date and Time,视图切换到相应视图,单击左上角的Root按钮,视图回到Root View。每次进入Date and Time视图,显示的时间都会不同:

     

17、接下来,我们将要实现,单击List行,显示一个表格,并且单击表格中的某一行,我们可以在新弹出的视图中编辑该行内容。首先创建ViewController文件:ListViewController、ListEditViewController,前者继承UITableViewController,后者继承UIViewController,参照第10步。都不要创建XIB文件。

然后打开MainStoryboard.storyboard,拖一个Table View Controller和View Controller到编辑区域,调整所有视图在编辑区域的位置,如下图:

设置新拖入的Table View Controller和View Controller的class属性分别是ListViewController和ListEditViewController,参考第11步。

18、参照第14步,从Root View Controller中的List那一行向List View Controller拉线,并在弹出菜单也选择Push。然后选中List View Controller的Navigation Item,设置Title及Back Button都为List,可以参照第9步。

19、向List View Controller中的表格区域拖入一个Table View Cell,这样其中就有两个Cell了。设置第一个Cell的Identifier属性为GreenIdentifier。向第一个Cell中拖入一个Label,设置其字体颜色为绿色。同样对第二个Cell进行设置,Identifier属性为RedIdentifier,往其中拖入Label,设置字体颜色为红色。两个Label的Tag属性都设为1。

20、打开ListViewController.m,向其中添加代码:

20.1 在#import的下一行添加代码:

@interface ListViewController ()
@property (strong, nonatomic) NSMutableArray *listArray;
@property (copy, nonatomic) NSDictionary *editedSelection;
@end

20.2 在@implementation之后添加代码:

@synthesize listArray;
@synthesize editedSelection;

20.3 找到viewDidLoad方法,向其中添加代码:

- (void)viewDidLoad {
    [super viewDidLoad];
    NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:
                             @"Horse", @"Sheep", @"Pig", @"Dog",
                             @"Cat", @"Chicken", @"Duck", @"Goose",
                             @"Tree", @"Flower", @"Grass", @"Fence",
                             @"House", @"Table", @"Chair", @"Book",
                             @"Swing" ,nil];
    self.listArray = array;
}

20.4 找到numberOfSectionsInTableView方法,使其返回1,并删掉#warning。

20.5 找到numberOfRowsInSection方法,删掉#warning,使其返回[listArray count]:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    return [listArray count];
}

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSUInteger row = [indexPath row];
    NSString *identifier = nil;
    if (row%2 == 0) {
        identifier = @"GreenIdentifier";
    }else 
        identifier = @"RedIdentifier";
  
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    
    UILabel *cellLabel = (UILabel *)[cell viewWithTag:1];
    cellLabel.text = [listArray objectAtIndex:row];
    
    return cell;
}

21、运行一下,当单击List行时,页面切换到我们List视图:

  

22、下面实现单击List表格中的某一行,视图切换,并且视图中的内容与之前选中的行相关,然后可以对其进行编辑,返回后,原来的数据也会发生改变。

打开MainStoryboard.storyboard,仿照第14步,从List View Controller中的两行向List Edit View Controller拉线,在弹出菜单选择Push。这样List Edit View Controller视图中就出现了Navigation Item,选中它,设置Title为Edit。这样,单击List表格中的某一行,视图都会切换到List Edit View Controller。

23、打开ListViewController.m,在@end之前添加代码:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    //获取目的ViewController
    UIViewController *destination = [segue destinationViewController];
    if ([destination respondsToSelector:@selector(setPreViewController:)]) {
        //将自身传递给目的ViewController
        [destination setValue:self forKey:@"preViewController"];
    }
    if ([destination respondsToSelector:@selector(setSelection:)]) {
        //目的ViewController中的selection属性存储的就是需要编辑的内容及其在表格中的位置
        NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
        id object = [self.listArray objectAtIndex:indexPath.row];
        NSDictionary *selection = [NSDictionary dictionaryWithObjectsAndKeys:
                                   indexPath, @"indexPath",
                                   object, @"object",
                                   nil];
        [destination setValue:selection forKey:@"selection"];
    }
}

在ViewDidUnload方法之后添加代码:

- (void)setEditedSelection:(NSDictionary *)dict {
    if (![dict isEqual:editedSelection]) {
        editedSelection = dict;
        NSIndexPath *indexPath = [dict objectForKey:@"indexPath"];
        id newValue = [dict objectForKey:@"object"];
        [listArray replaceObjectAtIndex:indexPath.row withObject:newValue];
        [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                              withRowAnimation:UITableViewRowAnimationAutomatic];
    }
}

24、打开MainStoryboard.storyboard,找到Edit视图,向其中拖一个Text Field:

然后为这个Text Field向ListEditViewController.h中创建Outlet映射,名称为editText。

25、打开ListEditViewController.h,向其中添加属性:

@property (copy, nonatomic) NSDictionary *selection; 
@property (weak, nonatomic) id preViewController;

26、打开ListEditViewController.m,添加代码:

26.1 在@implementation的下一行添加代码:

@synthesize preViewController;
@synthesize selection;

26.2 找到ViewDidLoad方法,它默认是被注释掉的,去掉其周围注释符,添加代码如下:

- (void)viewDidLoad
{
    [super viewDidLoad];
    editText.text = [selection objectForKey:@"object"]; 
    [editText becomeFirstResponder]; 
}

26.3 在ViewDidUnload方法之后添加代码:

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated]; 
    
    if ([preViewController respondsToSelector:@selector(setEditedSelection:)]) {
        //结束编辑
        [editText endEditing:YES];
        NSIndexPath *indexPath = [selection objectForKey:@"indexPath"];
        id object = editText.text;
        NSDictionary *editedSelection = [NSDictionary dictionaryWithObjectsAndKeys:
                                         indexPath, @"indexPath",
                                         object, @"object",
                                         nil];
        //设置上一个ViewController中的editedSelection,由于设置editedSelection方法
        //已经重写,从而对应在表格中的数据会发生变化
        [preViewController setValue:editedSelection forKey:@"editedSelection"];
    }
}

27、运行:

  

单击List行时,视图切换到上面右图所示。然后单击Pig那一行,视图切换到Edit视图,然后编辑内容,之后返回,这样,原来表格中的内容就会发生改变:

  

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

 

© 著作权归作者所有

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

评论(31)

p
perfectcn

引用来自“perfectcn”的评论

写的很好很详细, 受益匪浅,谢谢分享。
我使用的是XCODE7,使用中在List中点击Pig或其它进入编辑后,编辑完毕返回时报异常。遇到类似问题的可以参考
在 setEditedSelection 函数中
[ListArray replaceObjectAtIndex: indexPath withObject: newValue];
调整为:
[ListArray replaceObjectAtIndex: indexPath.row withObject: newValue];
这样在编辑完返回上级菜单时就没有异常了。
班门弄斧,见笑了。

抱歉,原来代码上就有.row,是我自己敲的时候漏掉了,原来代码没有问题
p
perfectcn
写的很好很详细, 受益匪浅,谢谢分享。
我使用的是XCODE7,使用中在List中点击Pig或其它进入编辑后,编辑完毕返回时报异常。遇到类似问题的可以参考
在 setEditedSelection 函数中
[ListArray replaceObjectAtIndex: indexPath withObject: newValue];
调整为:
[ListArray replaceObjectAtIndex: indexPath.row withObject: newValue];
这样在编辑完返回上级菜单时就没有异常了。
班门弄斧,见笑了。
l
lizhi0123
0
1982_06_01
1982_06_01
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
这个函数不是太明白,怎么样把数据加载到列表中的呢,UI中的两个已经存在的TableCell为什么没有了,是默认进入队列了吗?
张雪萍
很有用,谢谢分享。
Settings
Settings
最后那个修改不能输中文吗
z
zk0301
这个要慢慢操作了 先下一篇 冲啊
双子座
双子座 博主

引用来自“997191854”的评论

lz讲的很细致到位。,我看了几本讲ios的,不是太高深就是不实用,有没有什么好的资料可以推荐的?

ps:lz都是自学成才的么,佩服

在掌握了一些基础和技巧后,很多东西可以自己琢磨出来。我是看的英文资料,你可以到Apress出版社官网上查查
9
997191854
lz讲的很细致到位。,我看了几本讲ios的,不是太高深就是不实用,有没有什么好的资料可以推荐的?

ps:lz都是自学成才的么,佩服
双子座
双子座 博主

引用来自“纪流云”的评论

请问用Storyboard怎样自定义cell样式呢?

自己想想吧,其实不难。让程序按照自己的思想运行
iOS开发需要了解的基础内容链接整理

https://llvm.org/svn/llvm-project/cfe/trunk/test/SemaObjC/builtinobjcnslog.m http://llvm.org/klaus/clang/commit/5faf5d31fa634e1fdb576c4d9708cd4efa5ea310/ 对Objective-C的NSObjec......

智能小松鼠
2015/01/14
299
2
使用 Interface Builder 兼容 iOS6 和iOS7

当你在更新你的App到iOS 7的平台时遇到最大的挑战之一就是确保不要遗忘那些还在使用iOS 6平台的用户,在此我们提供一些建议使你的App应用在iOS 6和iOS 7上同时保留视觉吸引力和技术功能. 此图...

isaced
2014/01/15
13.4K
12
IOS storyboard 使用链接整理

Tutorial:Storyboards:https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/RoadMapiOS/SecondTutorial.html Adding a Scene to a Storyboard:https://d......

智能小松鼠
2015/02/03
210
0
一步一步学习 iOS 6 编程(第四版)正式发布

所有范例程序及其截图都采用Xcode 4.4 和Xcode 4.5 最新版开发工具,本书包含了最新的iOS 6 开发技术,如自动布局(Auto Layout)、集合视图(Collection View)等等。 新增内容包括:分割视...

entlib
2012/10/25
837
2
一步一步学习iOS 5编程(第三版)-PDF中文版-正式发布!

目前,这是第一本介绍iOS 5.x 和 Xcode 4.4 的中文版书籍,尤其适合于iOS 编程开发初学者。本教程由 EntLib.com 团队编写。如有任何技术问题,欢迎留言。 电子版 – PDF 格式,支持iPhone、i...

entlib
2012/09/20
795
2

没有更多内容

加载失败,请刷新页面

加载更多

全面兼容IE6/IE7/IE8/FF的CSS HACK写法

浏览器市场的混乱,给设计师造成很大的麻烦,设计的页面兼容完这个浏览器还得兼容那个浏览器,本来ie6跟ff之间的兼容是很容易解决的。加上个ie7会麻烦点,ie8的出现就更头疼了,原来hack ie...

前端老手
13分钟前
3
0
常用快递电子面单批量打印api接口对接demo-JAVA示例

目前有三种方式对接电子面单: 1.快递公司:各家快递公司逐一对接接口 2.菜鸟:支持常用15家快递电子面单打印 3.快递鸟:仅对接一次,支持常用30多家主流快递电子面单打印 目前也是支持批量打...

程序的小猿
16分钟前
5
0
Yii 框架中rule规则必须搭配验证函数才能使用

public $store_id;public $user_id;public $page;public $limit;public $list;public $mch_list;public $cart_id;public $is_community;public $shop_id;public $cart_typ......

chenhongjiang
19分钟前
2
0
Flutter使用Rammus实现阿里云推送

前言: 最近新的Flutter项目有“阿里云推送通知”的需求,就是Flutter的App启动后检测到有新的通知,点击通知栏然后跳转到指定的页面。在这里我使用的是第三方插件Rammus来实现通知的推送,之...

EmilyWu
19分钟前
40
0
Knative 实战:三步走!基于 Knative Serverless 技术实现一个短网址服务

短网址顾名思义就是使用比较短的网址代替很长的网址。维基百科上面的解释是这样的: 短网址又称网址缩短、缩短网址、URL 缩短等,指的是一种互联网上的技术与服务,此服务可以提供一个非常短...

阿里巴巴云原生
34分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部