ios storyboard全解析 (二)

摘要:
我们将接着上次的课程开始,所以打开你上一次的工程,或者下载上一次的源代码.好了,让我们深入storyboard一些其他屌炸天的功能吧!
ios storyboard全解析 (二)第1张

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

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

ios storyboard全解析 (二)第2张

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

介绍Segue

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

ios storyboard全解析 (二)第3张

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

ios storyboard全解析 (二)第4张

Reminder:

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


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

ios storyboard全解析 (二)第5张

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

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

ios storyboard全解析 (二)第6张

这就是所谓的”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.

ios storyboard全解析 (二)第7张

接下来,使用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对象,然后松开鼠标,弹出一个菜单,对应名称选择,如下图:

ios storyboard全解析 (二)第8张

请注意你赋给取消方法的名字.当你创建一个unwind segue的时候,在整个app中,这个列表都将显示所有的unwind方法(即一个带有签名的方法@IBAction func methodname(segue:UIStoryboardSegue)),所以确保你能认出你创建的名字代表的意思.
运行app,点击’+’号按钮,测试Cancel按钮和Done按钮.很多功能但是使用很少的代码!

静态单元格(static cell)

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

ios storyboard全解析 (二)第9张

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

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

ios storyboard全解析 (二)第10张

Note:

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


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

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

ios storyboard全解析 (二)第11张

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

ios storyboard全解析 (二)第12张

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

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

ios storyboard全解析 (二)第13张

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

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

ios storyboard全解析 (二)第14张

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

ios storyboard全解析 (二)第15张
Paste_Image.png

Note:

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

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

ios storyboard全解析 (二)第16张
Paste_Image.png

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


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

ios storyboard全解析 (二)第17张

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

// MARK: - Table view data source

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

ios storyboard全解析 (二)第18张

还有一件关于静态单元格的事情:它们只工作在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周围,该行就会高亮显示.

ios storyboard全解析 (二)第19张

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

免责声明:文章转载自《ios storyboard全解析 (二)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇斗鱼直播三面:说说JDK与JRE的区别是什么!JQuery 数据加载中禁止操作页面下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

静态文件cdn自解析生成相对路径

一、场景和目标:用户上传一个包含 index.html 的静态资源压缩包,资源内所有文件都是相互依赖的,不需要用户对内部文件内容做任何特殊处理,仅通过服务端逻辑处理达到用户访问 http://xxx.xxx/guid/index.html 时就可以得到这个资源的所有数据并正常浏览。 二、技术:nodejs、expressnpm 包:decompress、r...

EasySharding.EFCore 如何设计使用一套代码完成的EFCore Migration 构建Saas系统多租户不同业务需求且满足租户自定义分库分表、数据迁移能力?

下面用一篇文章来完成这些事情 多租户系统的设计单纯的来说业务,一套Saas多租户的系统,面临很多业务复杂性,不同的租户存在不同的业务需求,大部分相同的表结构,那么如何使用EFCore来完成这样的设计呢?满足不同需求的数据库结构迁移 这里我准备设计一套中间件来完成大部分分库分表的工作,然后可以通过自定义的Migration 数据库文件来迁移构建不同的租户数据...

详细介绍MySQL/MariaDB的锁

官方手册:https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-transaction-model.html 1.事务提交的方式 在MariaDB/MySQL中有3种事务提交的方式。 1.显式开启和提交。 使用begin或者start transaction来显式开启一个事务,显式开启的事务必须使用...

OO实现ALV TABLE 十:ALV的页眉页脚

除了可以通过类CL_SALV_EVENTS_TABLE的事件设置ALV的页眉页脚之外,还可以通过类CL_SALV_TABLE的方法SET_TOP_OF_LIST,SET_TOP_OF_LIST_PRINT, SET_END_OF_LIST,SET_END_OF_LIST_PRINT这四个方法。页眉页脚的显示可以设置显示和打印时不一样,打印时的页眉页脚通过方...

第12章 DOM操作

目录 *1. 向DOM中注入HTML 1.1 将HTNL字符串转换成DOM 预处理HTML源字符串 包装HTML 1.2 将DOM元素插入到文档中 2. DOM的特性和属性通过DOM方法和属性访问特性值 3. 令人头疼的样式特性 3.1 样式在何处 3.2 样式属性命名一种访问样式的简单方法 3.3 获取计算后样式 3.4 测量元...

用POI导出excel时,较长的数字不想被自动变为科学计数法的解决方式

做过很多次导出excel了。都碰到一个问题,内容里如果包含一个比较长的数字,比如订单号“2546541656596”,excel会自动变成科学计数法。。。 弄过好几次都没有解决,最近又要导出excel了,下决心一定要找到解决办法 自己在excel里测试过,较长的数字,都会自动变成科学计数法,除非我们把单元格格式设置成“文本型” 哈哈,似乎找到了思路:用po...