iOS 9 Storyboard 教程(二上)


Add Player 最终的设计看上去像下面这样:#接第一部分:
原帖地址
简书地址

如果你想了解storyboards,那么你来对地方了.
在第一篇文章第一篇文章中,你已经学到了Interface Builder的基本用法来创建和连线多个控制器,以及使用在storyboard中可以通过直接创建自定义的tableViewCell.
此次storyboard系列教程的第二部分,也是最后一部分,我们将了解到segue,静态的tableViewCell,添加玩家的控制器,以及一个游戏选择控制器!
我们将接着上次的课程开始,所以打开你上一次的工程,或者下载上一次的源代码.


好了,让我们深入storyboard一些其他屌炸天的功能吧!

介绍Segue

时候在storyboard中添加更多的控制器了.你激昂会创建一个控制器,它允许用户向这个app中添加玩家.
打开Main.storyboard,然后在右侧的导航栏里拖拽一个BarButtonItem到tableView里的Players上.在Attributes inspector改变identifier和在BarButtonItem属性里将System Item改为Add,这样会添加一个’+’号按钮.



当用户点击这个按钮的时候,你想要这个app弹出一个新的模态控制器,可以输入一个新玩家的详细信息.
拖一个新的Table View Controller到storyboard里.需要记住的是,你可以通过双击来缩小storyboard里的控件,这样你就可以更多得空间来工作了.当新的TableViewController选中的时候,选择Editor\Embed in\Navigation Controller.用鼠标选中’+’按钮,按住ctrl,拖拽到新建的控制器里,释放鼠标会出现一个小的弹出框.之后选择present modally.如下图:


Reminder:

当缩小storyboard的时候,你不能进行添加或修改.如果你创建的segue有问题,尝试双击把storyboard缩放回原来的大小!


然后在Player控制器和导航控制器之间就会出现一个新的箭头:



连接的类型是segue(发音:赛格威),表示从一个控制器到另一个控制器的过渡.到目前为止,你所看到的storyboard 上的连线都是一个个的关系并且它们描述了一个包含另一个的view controller.在另一方面,segue所做的改变都在控制器上.通过点击button,tableViewCell,手势等等来触发segue.
使用segue最屌的就是,你不必写任何代码来present新的控制器,也不必使用IBAction方法连接按钮.你所做的只有从Bar Button Item 拖动到下一个控制器,就足以创建一个过渡了.(Note:如果你的控件已经实现了IBAction连接,那么segue会重写它).

运行app,然后点击’+’号按钮.一个新的tableView就会从下往上滑出.


这就是所谓的”modal” segue.新的控制器完全把先前的界面盖住了.用户不能与底层的控制器进行交互直到把modal出来的控制器关闭为止.后面你也会”看到”segue在导航控制器(Navigation Controller.)的导航栈里推出一个新的控制器.

然而新的控制器并不是非常有用 – 你甚至不能关闭它返回到上一个控制器.那是因为只有一个方法–虽然它可以从Player控制器到这个新的控制器,但是它却不能返回.

Storyboard提供了一个称为unwind segue的特性,它使得Storyboard可以具有返回的能力.这个是你接下来要实现的内容.主要有3步:

1.为用户创建一个选择对象,通常是一个按钮.

2.在控制器里创建一个unwind方法,可以返回到上一个控制器.

3.在storyboard中连接方法和对象.

首先,打开Main.storyboard,选择这个新创建的TableViewController .改变它的标题为Add Player(双击导航栏即可修改).然后在导航栏的两侧各添加一个Bar Button Item.在Attributes inspector,设置左侧按钮的System Item属性为Cancel,右侧按钮为Done.



接下来,使用Cocoa Touch Class模板添加一个新的文件继承于UITableViewController,命名为PlayerDetailsViewController.切换到Main.storyboard ,选择Add Player控制器.在Identity inspector设置它的Class为PlayerDetailsViewController.我总是忘记这至关重要的一步,所以确保你没有忘记;后面我还会指出.
现在你可以创建最终的unwind segue了.在PlayersViewController.swift(而不是detail控制器)类末尾添加unwind 方法:

@IBAction func cancelToPlayersViewController(segue:UIStoryboardSegue) {}
@IBAction func savePlayerDetail(segue:UIStoryboardSegue) {}

cancelToPlayersViewController(_:)这个方法名仅仅为了unwind方法标记.

最后,切换回Main.storyboard ,然后分别连接Cancel按钮和Dnoe按钮的方法.按住ctrl并用鼠标拖拽到视图控制器的Exit对象,然后松开鼠标,弹出一个菜单,对应名称选择,如下图:

请注意你赋给取消方法的名字.当你创建一个unwind segue的时候,在整个app中,这个列表都将显示所有的unwind方法(即一个带有签名的方法@IBAction func methodname(segue:UIStoryboardSegue)),所以确保你能认出你创建的名字代表的意思.

运行app,点击’+’号按钮,测试Cancel按钮和Done按钮.很多功能但是使用很少的代码!

静态单元格(static cell)

当你完成这个部分的时候,Add Player控制器看上去和下图差不多:


这是一个分组的table view,但是你不需要为这个表格创建一个数据源.你可以在storyboard直接设计它–不必在写cellForRowAtIndexPath(_:)方法!使这成为可能的的特性被称为静态单元格(static cells).

在Add Player控制器里选择table view,然后在Attributes inspector里把Content改为Static Cells.把Style从Plain改为Grouped并且将Sections设置为2.


Note:

当你改变了Sections属性的值以后,编辑器将会复制现有的section.(你也可以在左侧Document Outline里选择具体的section).


完成后的控制器只有每组一行,所以现在在每个组中都有2个cell,在Document Outline可以删除它们.

选择Table View最顶部的Section(从Document Outline).在Attributes inspector里,把Header属性的值设置Player Name.


拖拽一个TextField到这个组的cell里.拉伸它的宽然后去除它的border,那样你就不会看到text field的开始和结尾.设置字体大小17.0,不勾选Adjust to Fit.



你可以点击Xcode的助理编辑器(Assistant Editor),之后将text field和PlayerDetailsViewController做一个连线.在storyboard里,从工具栏里打开Assistant Editor(右上方有两个环重叠的按钮).它应该自动地打开PlayerDetailsViewController.swift.

选择textField然后按住ctrl,并用鼠标拖拽到.swift文件的顶部,类定义的底部.当弹框出现的时候,命名这个新的连接为nameTextField,然后点击Connect.在你点击Connect之后,Xcode将添加这个属性到PlayersDetailViewController类里而且会和storyboard相连:


在表的单元格里创建视图的连线正是我所说的你不应尝试用原型单元格,而用静态单元格是可以的.每一个静态单元格都只有一个实例,所以它完全是可以接受的在视图控制器里通过连线连接它们的子视图.

设置第二组静态单元格的Style为Right Detail.这样就会为你显示一个标准的单元格样式.双击把左侧的label名字改为Game,然后给这个单元格一个名为Disclosure Indicator的附件.,如下图:

正如你命名text field所做的,同样也为右侧的label添加一个连线(右侧名为”Detail”的那个),并且命名它为detailLabel.在这个单元格上的标签只是一个平常的UILabel对象.在按住ctrl并拖拽到PlayerDetailsViewController.swift文件的时候,你也许需要点击几次才能选中这个标签(而不是整个单元格).一旦完成了,它就会像下面这样:

Paste_Image.png

Note:

到目前为止,在storyboard中你所设计的控制器都是在4.7英寸的iPhone6上运行的.显而易见,你的app应该能适配所有的屏幕尺寸,你可以在Storyboard中预览所有这些尺寸.

从工具栏打开Assistant Editor ,然后在跳转栏里选择Preview.在辅助编辑器的左下方,点击’+’号符号,添加新的屏幕尺寸来预览.想要去除一个屏幕尺寸,选中它然后点击Delete键删除.

Paste_Image.png

对于Ratings app来说,你不需要做任何想做的事.只需要使用table view controller然后它会根据不同设备尺寸自动地调整尺寸到合适的大小,你将会使用Auto Layout 和 Size Classes.


现在编译和运行,你会注意到Add Player仍然是空的!



当你使用静态单元格的时候,你的table view controller不需要爱一个数据源.虽然你使用了Xcode得模板来创建的PlayerDetailsViewController类,但是它还是有数据源的占位符,并且在正常工作状态会显示这个静态单元格–那就是为什么你的静态内容没有变量.是时候来解决它了!
打开PlayerDetailsViewController.swift并且删除所有从下面开始的行(除了类的大括号):

// MARK: - Table view data source

运行app然后检查带有静态单元格的控制器.所有的不用写一行代码–事实上,你扔掉了一堆代码!



还有一件关于静态单元格的事情:它们只工作在UITableViewController里.即使Interface Builder会让你添加它们到一个内置UIViewController的Table View对象,在运行时期间将不会起作用,原因是因为UITableViewController提供了一个负责静态单元格数据源的额外机制.Xcode为了防止你编译这个工程,甚至会输出错误信息:”(非法的配置:静态表视图只在嵌入到UITableViewController实例里才有效.)Illegal Configuration: Static table views are only valid when embedded in UITableViewController instances”.在另一方面,基本的单元格也可以在一个内置tableView的视图控制器里起作用.


Note:

如果你创建了一个有很多静态单元格的控制器–很多都适合可见的frame–然后你可以用鼠标或触摸板滑动手势(2指点击)滑动它们在Interface Builder里.这也许不会立即就可以看见,但是它确实起作用.


你不能避免写代码,甚至是使用静态单元格的table view也是如此.当你拖拽textField到第一个单元格的时候,你可能注意到它并不是完全合适.在textField周围有一个小的间距.用户不能看到textField从何处开始或结束,所以如果他们点击了边界的地方,键盘没有出现,他们将会感到困惑.

为了避免出现这种情况,你应该让用户点击任何地方都能弹出键盘.那非常简单实现–只打开PlayerDetailsViewController.swift然后添加tableView(_:didSelectRowAtIndexPath:)方法如下所示:

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
  if indexPath.section == 0 { 
  nameTextField.becomeFirstResponder() 
  }
}

那也就是说,如果用户点击了第一个单元格,app将会响应textField.这个section里只有一个单元格,所以你只需要检查这个section的索引就可以了.让textField作为第一响应者会自动弹出键盘.只需要一个小小地调整,但是却可以省去用户的焦虑.


Tip:

当添加一个代理方法或者重写一个view controller的方法,只需要输入方法的名称(不用在前面加”func”),然后你将可以从出现的方法列表里选择正确的方法.


你也要在storyboard的Attributes inspector里设置Selection Style为None(而不是Default),否则如果用户点击textField周围,该行就会高亮显示.



好了,这就是设计的 Add Player控制器.现在让我们在实际工作中使用它吧.

后续更新敬请期待

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容