- (void) prepareForSegue:(UIStoryboardSegue
*)segue sender:(id)sender
{
NSLog(@"Source Controller
= %@", [segue sourceViewController]);
NSLog(@"Destination
Controller = %@", [segue destinationViewController]);
NSLog(@"Segue Identifier
= %@", [segue identifier]);
if ([[segue identifier]
isEqualToString:@"MyViewController"])
{
SecondViewController
*viewController = [segue destinationViewController];
viewController.dataModel
= ...
}
3.在两个场景之间传递数据 Segue连接对象
当两个场景进行转换的时候,storyboard运行时 会创建一个segue对象,是UIStoryboardSegue的类。
当前源视图控制器会接收 prepareForSegue:sender: 消息,我们可以使用如下代码来向目标视图控制器传递数据:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// 判断启动的目标View是否为MyViewController
if([[segue destinationViewController] class] == [MyViewController class])
{
MyViewController *myView = [segue destinationViewController];
[myView setText:@"李宁"];
}
}
通过以上代码可以看到,在- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sende函数调用的时候,目标视图控制器对象在Segue对象中已经被创建好了,所以可以把要传递的数据赋值给目标控制器对象的属性,也可以通过调用目标控制器对象的方法来传递参数。
注意: 通过测试发现segue函数先于目标控制器的viewWillAppear 调用
4.设置默认启动的StoryBoard
在一个程序中,我们可以创建多个storyboard,但是需要指定一个 main
storyboard,这样当程序启动的时候会自动的加载mai storyboard,其余的story board只能显式的进行加载了。
指定main storyboard
显式加载一个storyborad:
UIStoryboard* sb
= [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
NewViewController*
newViewController = [sb instantiateViewControllerWithIdentifier:@"NewViewController"];
三 使用技巧
1.将入口由View变成了
UINavigationController
选中storyboard默认的View, 然后点击“Editor”>“Embed In”>“Navigation Controller”菜单项,XCode就会自动在storyboard上生成一个UINavigationController,并更改启动入口。
2.手动实现UIStoryboardSegue
为了在两个视图切换时候实现一些翻转特效,我们可以手动来实现自己的segue.
a.定义我们自己的Segue MyStoryboardSegue
第一个
@interface MyStoryboardSegue
: UIStoryboardSegue
-
(void)perform;
@end
@implementation MyStoryboardSegue
- (void) perform {
UIViewController *src = (UIViewController *) self.sourceViewController;
UIViewController *dst = (UIViewController *) self.destinationViewController;
[UIView transitionWithView:src.navigationController.view duration:0.5
options:UIViewAnimationOptionTransitionNone
animations:^{
[src.navigationController pushViewController:dst animated:YES];
}
completion:NULL];
}
@end
第二个
#import <UIKit/UIKit.h>
@interface CustomModal
: UIStoryboardSegue
- (void)perform;
@end
#import "CustomModal.h"
@implementation CustomModal
- (void) perform
{
UIViewController *current
= self.sourceViewController;
UIViewController *next
= self.destinationViewController;
[current presentViewController:next animated:YES completion:nil];
}
@end
上面代码中我们定义了两个segue类。
手动实现一个segue很简单,我们只要继承UIStoryboardSegue类,然后重载-(void)perform方法,在该方法里面实现自己的逻辑就OK了。
b.在IB中使用自己定义的Segue
c.手动调用自己的segue
-(void) viewDidAppear:(BOOL)animated
{
//调用模式视图的时候不能在viewDidLoad中进行调用
[self performSegueWithIdentifier:@"aabb" sender:self];
}
使用UIStoryboard还应该注意的问题:
1.孤儿View(独立于ViewController的View)是不能出现在StoryBoard里的,View必须通过ViewController来管理,StoryBoard更像是Controller对象的容器,而不是View对象的容器,NIB/XIB可以作为View对象的容器。
2.ViewController之间的过渡代码(-presentModalViewController:animated:和-pushViewController:animated:)已经是历史了,用StoryBoard可以直接可视化地连接不同的ViewController。
3.UIWindow对象的作用被进一步淡化,甚至可以这么说:其实很多程序根本无需用到UIWindow对象。AppDelegate也不再被鼓励(也不能)用来做ViewController--你甚至无法在Interface
Builder的StoryBoard图上找到AppDelegate对象--因为它本来就不应该用来处理界面(View)的。(AppDelegate的作用很简单,就是处理UIApplication的回调,而不应该负责用户界面的处理,ViewController来负责处理View才是正确)
四 总结
StoryBoard是iOS
5的新特征,旨在代替历史悠久的NIB/XIB(其实StoryBoard还是基于NIB/XIB的,不过开发人员已经无需直接跟NIB打交道了)。
NIB文件也是用来描述用户界面的,NIB文件和ViewController相关联,他们是一对一的关系,使用NIB可以减少对界面的设计代码。而StoryBoard的出现,则是我们更加快速构建界面,整个程序的视图可以展现在一个storyboard中,可以作为程序的“设计图”来用,方便了我们对这个程序的视图结构的把握,而且使用storyboard的segue可以轻松的实现两个场景的跳转。
总之,使用Storyboard能够减少很多跟View相关的代码,使View和Controller进一步解耦,能够优化程序的“页面流”,让我们编写更加符合MVC模式的代码,使程序结构更加合理清晰。