Xcode 7 带来了如下新特性:
storyboard references
将他们连接起来 supplementary views
之前团队开发一般都避免使用 storyboard,因为最后 merge 的时候着实蛋疼。现在的 Xcode 7 允许每个人维护一个小 storyboard ,然后通过 storyboard references
将这些 storyboards 连接起来,一举解决了冲突问题。
一般可以考虑将一个容器 view controller 单独放到一个新 storyboard 中。
拖选 scene,选择 Editor/Refactor to Storyboard
,输入 name
,设置 Gruop
,保存。
Xcode 做了这么三件事:
view controllers
指向其他 storyboard 这个新创建的 storyboard 中 scenes 的布局和之前的也是一模一样
原来的 main storyboard 变成了下面的样子
被移走的 scenes 变成了 storyboard reference
如果 Editor/Refactor to Storyboard
这步没有输入 name
,Xcode 会自动给你生成一个,还是自己起一个有含义的名字吧
还是在 main storyboard 中,注意被移走的 scenes 留下了一个 ChecklistsNavigationController
(referenceID),其实这个 ID 对应着将会 segue 的 VC
你也可以移除这个 referenceID
,这样默认的 segue 指向下一个 storyboard 中的 Initial View Controller (当然你要在该 storyboard 中设置了 Initial View Controller 才行)
如果你是一个团队成员,tabBar VC 里面的一个 VC 由你的同事完成,现在需要集成起来。步骤也很简单:
在 Main.storyboard 所在目录层级,点击 File/Add Files to 『当前工程目录』,选择你同事完成的文件夹(包含 swift 和 storyboard 文件),再到 Main.storyboard 中创建一个 storyboard reference
指向这个新创建的文件夹中的 storyboard
如果你有一个很大的工程,导航到达一个场景需要点击很多次,进入很多层级才能实现,此时可以按照功能单元来划分 storyboard,比如下面的,将点击 tableView cell 进入详情页面单独划分到一个 storyboard 中
剩下的操作和上面相同,现在我们回到主程序界面,在 Main Interface
中选择我们刚才创建的 storyboard
这样做的好处是,运行程序会直接从该 storyboard 的起始 VC 运行,也就是 App 一运行就会进入详情页面
注意,因为没有从 main.storyboard 以及前面的 storyboard 启动,因此也不会出现 navigation bar
或 tab bar
还有要注意的一点是,如果当前的 initial VC 需要前面的 segue 提供数据,就会失败
storyboard 有一个容易被忽视的特性 scene dock ,在 storyboard 中选中一个 scene
注意到上面三个个小图标了吗?分别对应着:
Xcode 7 现在允许你添加自定义的 view 到这上面(scene dock)去了。添加到 scene dock 上的 view 并不会同时添加到 view controller 的 subviews 数组中去,但是,你可以通过 IBOutlets 连续的方式添加一个引用,方面在运行时使用这个 view。
我们为上面选中 tableView row 添加一个背景颜色,首先拖一个 view 到 tableView controller
的 secen dock
上。
下面改变这个 view 的背景色为橙色,最后通过 Ctrl-drag 从 cell 到 view 拉一条连线,在弹出的菜单中选择 selectedBackgroundView
,可供选择的还有 accessoryView
、 backgroundView
、 editingAccessoryView
。运行 OK~
并不支持多行选中启用的情形,因为在运行时只有一个 view 实例被创建,然后共享给各个 cell
如果你需要根据需要动态添加 View,那么就可以使用 scene dock 放置 view 的方式来实现,使用该方式的优势在于这个 view 不会对 view controller 中的 subviews 做出干扰,你可以之后使用代码方式动态将其添加到 view 层级结构中
现在我们来实现点击一行 table view cell,该行会 延展其高度 得到额外的空间显示 note,再次点击或点击不同的 row 又会恢复回去。
这次依然是拖一个 view 到 scene dock 上,设置 width:320
, height:128
。再拉一个 label 到这个 view 上,修改文字颜色(屎黄色:full_moon_with_face:)
接着拉一个 text view
到新 view 上紧挨着之前的 label 下面
现在可以从 notes view 到 view controller 拖一个 IBOutlet,尽管屏幕上一次会显示多个 cell 实例,但每次只有点击了才会展示 note view,且始终只会展示一个,所以不用太担心只有一个 IBOutlet 会出问题。
现在从 notes view 拉两个 IBOutlet:
notesView
(自身 view) notesTextView
(text view) 前面学过了 UIStackView ,这里确保 Auto Layout 约束了 notes view 的高度,然后添加到 cell 的 stack view 中去,设置 clipsToBounds 是为了在左滑删除时阻止 text view 跑到 cell 外面去
func addNotesViewToCell(cell: ChecklistItemTableViewCell) { notesView.heightAnchor .constraintEqualToConstant(notesViewHeight) .active = true notesView.clipsToBounds = true cell.stackView.addArrangedSubview(notesView) }
这里使用 Auto Layout,是因为 stack view 的高度源自于他 arrangedSubviews
,如果你这里不给 notesView 设置个高度,cell 不会在你添加 notes view 时自动增加高度。
下面移除 notes view:
func removeNotesView() { if let stackView = notesView.superview as? UIStackView { stackView.removeArrangedSubview(notesView) notesView.removeFromSuperview() } }
最后实现点击 cell row 出现 notes view 的效果:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { // 1 guard let cell = tableView.cellForRowAtIndexPath(indexPath) as? ChecklistItemTableViewCell else { return } // 2 tableView.beginUpdates() // 3 if cell.stackView.arrangedSubviews.contains(notesView) { removeNotesView() } else { addNotesViewToCell(cell) // 4 notesTextView.text = checklist.items[indexPath.row].notes } // 5 tableView.endUpdates() }
再次运行(这次注意将 Main Interface 改回 Main),点击任意 cell,你会看到 notes view 跑出来
这种方式创建的 view 只能由一个 VC 使用,如果 view 需要重用,那么还是用代码整吧
Xcode 7 现在支持在 navigation bar 上直接添加多个 buttons 了
拖一个 bar button item 到 navigation bar 上,xcode 会自动为你创建一个 Left Bar Button Items 和 Right Bar Button Items,现在添加两个 bar button 到 navigation bar 上来
你可以通过 rightBarButtonItems
或 leftBarButtonItems
来获取
navigationItem.rightBarButtonItems![1] = editButtonItem()
注意 leftBarButtonItems 数组中元素的顺序代表从左到右,而 rightBarButtonItems 则相反,代表从右到左,即最右边索引为 0