iOS 9 by Tutorials 笔记(九)

Chapter 9:What's New in Storyboards?

Xcode 7 带来了如下新特性:

  • 将单个 storyboard 分割成多个 storyboards,然后通过 storyboard references 将他们连接起来
  • 使用 scene dock 为 view controller 添加 supplementary views
  • 为 navigation bar 添加多个 buttons

Storyboard references

之前团队开发一般都避免使用 storyboard,因为最后 merge 的时候着实蛋疼。现在的 Xcode 7 允许每个人维护一个小 storyboard,然后通过 storyboard references 将这些 storyboards 连接起来,一举解决了冲突问题。

Creating your first storyboard reference

一般可以考虑将一个容器 view controller 单独放到一个新 storyboard 中。

拖选 scene,选择 Editor\Refactor to Storyboard,输入 name,设置 Gruop,保存。

Xcode 做了这么三件事:

  • 将选中的 scenes 放到新的 storyboard 中
  • 将 tab bar controller 的 view controllers 指向其他 storyboard
  • 将你带到新的 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 才行)

Storyboards within a team

如果你是一个团队成员,tabBar VC 里面的一个 VC 由你的同事完成,现在需要集成起来。步骤也很简单:

在 Main.storyboard 所在目录层级,点击 File\Add Files to 『当前工程目录』,选择你同事完成的文件夹(包含 swift 和 storyboard 文件),再到 Main.storyboard 中创建一个 storyboard reference 指向这个新创建的文件夹中的 storyboard

Focusing on a storyboard

如果你有一个很大的工程,导航到达一个场景需要点击很多次,进入很多层级才能实现,此时可以按照功能单元来划分 storyboard,比如下面的,将点击 tableView cell 进入详情页面单独划分到一个 storyboard 中

剩下的操作和上面相同,现在我们回到主程序界面,在 Main Interface 中选择我们刚才创建的 storyboard

这样做的好处是,运行程序会直接从该 storyboard 的起始 VC 运行,也就是 App 一运行就会进入详情页面

注意,因为没有从 main.storyboard 以及前面的 storyboard 启动,因此也不会出现 navigation bartab bar 还有要注意的一点是,如果当前的 initial VC 需要前面的 segue 提供数据,就会失败

Views in the scene dock

storyboard 有一个容易被忽视的特性 scene dock,在 storyboard 中选中一个 scene

注意到上面三个个小图标了吗?分别对应着:

  • 当前 VC 的引用
  • 第一响应者
  • unwind segues

Xcode 7 现在允许你添加自定义的 view 到这上面(scene dock)去了。添加到 scene dock 上的 view 并不会同时添加到 view controller 的 subviews 数组中去,但是,你可以通过 IBOutlets 连续的方式添加一个引用,方面在运行时使用这个 view。

我们为上面选中 tableView row 添加一个背景颜色,首先拖一个 viewtableView controllersecen dock 上。

下面改变这个 view 的背景色为橙色,最后通过 Ctrl-drag 从 cell 到 view 拉一条连线,在弹出的菜单中选择 selectedBackgroundView,可供选择的还有 accessoryViewbackgroundVieweditingAccessoryView。运行 OK~

并不支持多行选中启用的情形,因为在运行时只有一个 view 实例被创建,然后共享给各个 cell

Conditional views using the scene dock

如果你需要根据需要动态添加 View,那么就可以使用 scene dock 放置 view 的方式来实现,使用该方式的优势在于这个 view 不会对 view controller 中的 subviews 做出干扰,你可以之后使用代码方式动态将其添加到 view 层级结构中

现在我们来实现点击一行 table view cell,该行会延展其高度得到额外的空间显示 note,再次点击或点击不同的 row 又会恢复回去。

这次依然是拖一个 view 到 scene dock 上,设置 width:320height:128。再拉一个 label 到这个 view 上,修改文字颜色(屎黄色🌝)

接着拉一个 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 需要重用,那么还是用代码整吧

Using multiple bar buttons

Xcode 7 现在支持在 navigation bar 上直接添加多个 buttons 了

拖一个 bar button item 到 navigation bar 上,xcode 会自动为你创建一个 Left Bar Button Items 和 Right Bar Button Items,现在添加两个 bar button 到 navigation bar 上来

你可以通过 rightBarButtonItemsleftBarButtonItems 来获取

navigationItem.rightBarButtonItems![1] = editButtonItem()  

注意 leftBarButtonItems 数组中元素的顺序代表从左到右,而 rightBarButtonItems 则相反,代表从右到左,即最右边索引为 0


-EOF-

如果感觉此文对你有帮助,请随意打赏支持作者 😘

chengway

认清生活真相之后依然热爱它!

Subscribe to Talk is cheap, Show me the world!

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!