Storyboard全解析-第二部分转自:http://www.iteye.com/topic/1122984?如果你想了解更多Storyboard的特性,
Storyboard全解析-第二部分
转自:http://www.iteye.com/topic/1122984
?
如果你想了解更多Storyboard的特性,那么你就来对了地方,下面我们就来接着上次的内容详细讲解Storyboard的使用方法。?
在上一篇《Storyboard全解析-第一部分》中,我们介绍了如何使用storyboard来制作多种场景和如何将这些场景链接起来,我们还学习了如何自定义一个表格视图。?
接下来这部分,也是最后一部分,我们将讲解联线(segue),静态单元格等内容,我们还将加入一个选手详细内容页面,和一个游戏选择页面。?
Segues的介绍?
现在,让我们创建一个场景使用户可以自己增加新的选手进入列表。?
在Players界面中拖入一个Bar Button,放置在导航栏的右侧,在属性监视器中将他的Identifier改为“add”,这样他就会显示一个加号的按钮,当用户点击这个按钮时,他就会弹出一个新的场景让用户对新的内容进行编辑或添加。?
在编辑器中拖入一个新的Table View Controller,放置在Players场景的右边,然后按住ctrl,拉动加号键到新的场景中,这样,这个场景就会自动和这个按钮建立联系,从而自动归入Navigation View Controller中。?

?
放开鼠标之后,会出现如下选项:?

?
选中Modal,你可以注意到出现了一种新的箭头形式:?

?
这种链接形式被官方称为segue(pronounce: seg-way),我叫它联线,(其实是转换的意思)这种形式的联线是表示从一种场景转换到另外一种场景中,之前我们使用的连接都是描述一种场景包含另一种场景的。而对于联线来说,它会改变屏幕中显示的内容,而且必须由交互动作触发:如轻点,或其他手势。?
联线真正了不起的地方在于:你不再需要写任何代码来转入一个新的场景,也不用在将你的按钮和IBAction连接到一起,我们刚才做的,直接将按钮和场景链接起来,就能够完成这项工作。?
运行这个app,按下 + 键,会发现出现了一个新的列表。?

?
这种叫做 “modal” segue(模态转换),新的场景完全盖住了旧的那个。用户无法再与上一个场景交互,除非他们先关闭这个场景,过一会我们会讨论 push segue,这种segue会把场景推入导航栈。?
新的场景现在还没有什么用,你甚至不能把他关闭呢。?
联线只能够把你送到新的场景,你要是想回来,就得使用delegate pattern,代理模式。我们必须首先给这个新的场景设置一个独有的类,新建一个继承UITableViewController的类,命为PlayerDetailsViewController。?
为了把它和storyboard相连,回到MainStoryBoard,选择新建的那个Table View Contrller,将他的类设置喂PlayerDetailViewController,千万不要忘记这一步,这很重要。?
做完这一步之后,把新场景的标题改为“Add Player”,分别加入“Done”和“Cancel”两个导航栏按钮。?

?
修改PlayerDetailsViewController.h 如下:?
Java代码??

- @class?PlayerDetailsViewController;??
- ??
- @protocol?PlayerDetailsViewControllerDelegate?<NSObject>??
- -?(void)playerDetailsViewControllerDidCancel:??
- ??(PlayerDetailsViewController?*)controller;??
- -?(void)playerDetailsViewControllerDidSave:??
- ??(PlayerDetailsViewController?*)controller;??
- @end??
- ??
- @interface?PlayerDetailsViewController?:?UITableViewController??
- ??
- @property?(nonatomic,?weak)?id?<PlayerDetailsViewControllerDelegate>?delegate;??
- ??
- -?(IBAction)cancel:(id)sender;??
- -?(IBAction)done:(id)sender;??
- ??
- @end??
这会声明一个新的代理机制,当用户点击Cancel或者done按钮时,我们将用它来交互Add Player场景和主场景通讯。?
回到故事版编辑器,将Cancel和Done按钮分别与动作方法连接,一种方式是,按住Ctrl拖动到ViewController上,之后选择正确的动作。?

?
在 PlayerDetailsViewController.m,加入如下代码:?
Java代码??

- -?(IBAction)cancel:(id)sender??
- {??
- ????[self.delegate?playerDetailsViewControllerDidCancel:self];??
- }??
- -?(IBAction)done:(id)sender??
- {??
- ????[self.delegate?playerDetailsViewControllerDidSave:self];??
- }??
这是两个导航栏按钮要使用的方法,现在只需要让代理知道我们刚才加入了代码,而真正关闭场景只是代理的事情。?
一般来说一定要为代理制定一个对象参数,这样他才知道向那里发送信息。?
不要忘记加入Synthesize语句。?
Java代码??

- @synthesize?delegate;??
现在我们已经为PlayerDetailsViewController设置了一个代理协议,我们需要将这个协议的实现方法(implement)写在什么地方,很明显应该写在PlayerViewController因为这个vc代表了Add Player场景。在PlayersViewController.h中加入如下代码:?
Java代码??

- #import?"PlayerDetailsViewController.h"??
- ??
- @interface?PlayersViewController?:?UITableViewController?<PlayerDetailsViewControllerDelegate>??
并在PlayersViewController.m的结尾加入:?
Java代码??

- #pragma?mark?-?PlayerDetailsViewControllerDelegate??
- ??
- -?(void)playerDetailsViewControllerDidCancel:??
- ??(PlayerDetailsViewController?*)controller??
- {??
- ????[self?dismissViewControllerAnimated:YES?completion:nil];??
- }??
- ??
- -?(void)playerDetailsViewControllerDidSave:??
- ??(PlayerDetailsViewController?*)controller??
- {??
- ????[self?dismissViewControllerAnimated:YES?completion:nil];??
- }??
目前这个代理方法只能够跳转到这个新的场景中,接下来我们来让他做一些更为强大的事情。?
iOS 5 SDK中新添加的dismissViewControllerAnimated:completion: 方法可以被用来关闭一个场景。?
最后还有一件事情需要做,就是Players场景需要告诉PlayerDetailsVC他的代理在哪里,听上去这种工作在故事版编辑其中一拖就行了,实际上,你得使用代码才能完成。?
将以下方法加入到 PlayersViewController 中?
Java代码??

- -?(void)prepareForSegue:(UIStoryboardSegue?*)segue?sender:(id)sender??
- {??
- ????if?([segue.identifier?isEqualToString:@"AddPlayer"])??
- ????{??
- ????????UINavigationController?*navigationController?=??
- ??????????segue.destinationViewController;??
- ????????PlayerDetailsViewController??
- ??????????*playerDetailsViewController?=??
- ????????????[[navigationController?viewControllers]??
- ??????????????objectAtIndex:0];??
- ????????playerDetailsViewController.delegate?=?self;??
- ????}??
- }??
当使用Segue的时候,就必须加入这个名叫 prepareForSegue 的方法,这个新的ViewController在被加载的时候还是不可见的,我们可以利用这个机会来向他发送数据。?
请注意,这个segue的最终目标是Navigation Controller,因为这个是我们链接在导航栏上的按钮,为了获取PlayerDetailsViewController实例,我们必须通过NavController的属性来获取。?
试着运行一下这个应用,单击 + 键,然后试着关闭Add Player场景,仍然不管用。?
这是因为我们没有给Segue指定一个identifier,而parepareForSegu需要检查AddPlayer的身份证,这是必须的,因为你有可能会同时使用多个联线。?
为了解决这个问题,进入Storyboard的编辑器,点击Players场景和NavgationViewController场景之间的联线,你会注意到与这个连线相关的按钮会自动亮起来。?
在属性监视器中,将Identifier设置喂“AddPlayer”?

?
如果这是你再次运行这个应用,点击“Cancel”或者“Done”按钮,这个场景就会自动关闭并且返回到上一级场景。?
注意:从modal场景调用dismissViewControllerAnimated:completion方法是我们在这里使用的,但是这并不意味着你必须这样做。但是,如果你不是代理来完成这个关闭窗口的工作的话,唯一需要注意的是,如果你之前使用了[self.parentViewController dismissModalViewControllerAnimated:YES] 语句来关闭窗口的话,那么这个语句就不会正常工作了。?
顺便说一下,属性检查器中有一个Transition的选项,在这里你可以选择场景转换是的动画效果。?

?
试着运行一下,看看那种动画你最喜欢吧,但事情不要改变Style这个选项,如果你改变了,这个app可能会crash哦。?
我们接下来在这个教程中还会用到几次代理方法,下面我们来列一下为了完成一个连线,你需要做的几件事情。?