[关闭]
@zhangyuhangk 2015-07-22T06:51:16.000000Z 字数 3972 阅读 5296

UISplitViewController学习笔记(iOS8)

UISplitViewController iOS8 iOS


Storyboard如下:
storyboard
左边是split view controller
右上是master (或primary) view controller
右下是detail (或secondary) view controller

合并和展开(collapse & expand)

iOS8加入了size classes,并且允许iPhone上使用UISplitViewController。
当水平方向的size class为Compact时,split view显示为合并
当水平方向的size class为Regular时,split view显示为展开
可以使用iPhone6 Plus模拟器来运行,因为它竖屏的时候是Compact,横屏的时候是Regular。只要转一下就可以切换了,比较方便(以下均以iPhone6 Plus模拟器为例)。

合并和展开的时候会触发哪些事件或方法呢?

1. UISplitViewControllerDelegate

先设置delegate

  1. func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
  2. splitViewControler.delegate = self
  3. return true
  4. }

实现UISplitViewControllerDelegate

  1. extension AppDelegate: UISplitViewControllerDelegate {
  2. func splitViewController(splitViewController: UISplitViewController, collapseSecondaryViewController secondaryViewController: UIViewController, ontoPrimaryViewController primaryViewController: UIViewController) -> Bool {
  3. if some_condition {
  4. return false // collapse
  5. }
  6. return true // do not collapse
  7. }
  8. func splitViewController(splitViewController: UISplitViewController, separateSecondaryViewControllerFromPrimaryViewController primaryViewController: UIViewController) -> UIViewController? {
  9. if some_condition {
  10. return MySecondaryViewController()
  11. }
  12. return nil
  13. }
  14. }

split view controller合并时会调用splitViewController:collapseSecondaryViewController:ontoPrimaryViewController函数。如果不实现该函数或者返回false,则secondary view controller会合并到primary view controller上去。若返回true,则表示你自己处理了这个合并的行为,系统就不会再合并了。
展开时则调用splitViewController:separateSecondaryViewControllerFromPrimaryViewController函数。若不实现该函数或返回nil,则将原来合并到primary view controller上的secondary view controller拆分出来。
split view默认是展开的状态,当应用以竖屏启动时,系统会在显示前就作一次合并的动作。

2. UIViewController

上面说到split view controller会将secondary view controller合并到primary view contrller上,但是怎么实现合并的呢?
如果primary view contrller是个UINavigationController(大部分情况它都是),那secondary view contrller就是直接被push上去(即使secondary view contrller本身也是个UINavigationController)。
那如果primary view controller只是个普通的UIViewController呢?
iOS8为UIViewController添加了两个函数来响应合并和展开:

  1. func collapseSecondaryViewController(secondaryViewController: UIViewController, forSplitViewController splitViewController: UISplitViewController)
  2. func separateSecondaryViewControllerForSplitViewController(splitViewController: UISplitViewController) -> UIViewController?

行为和UISplitViewControllerDelegate的两个函数类似
默认的实现:
合并时,primary view controller只保存secondaryViewController的引用,UI没变化,还是只显示primary view controller
展开时,把secondaryViewController展开回来

3. UINavigationController

UINavigationController重写了上述两个函数,相应地调用了pushViewController和popViewController
注意:如果primary和secondary view controller都是UINavigationController。如下图:
storyboard

横屏时,各自显示为navigation view controller,并且 title的值不同,navigation bar的titleTextAttributes也不同
expand

合并时,secondary view controller显示在上面,包括title。但是此时navigation bar的样式(比如tintColor或titleTextAttributes)用的是primary view controller的!
collapse

如果希望合并后仍然使用secondary view contrller的样式,就需要在代码中显式赋值了。

  1. extension AppDelegate: UINavigationControllerDelegate {
  2. func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
  3. UIView.animateWithDuration(0.25) {
  4. let secondaryNavigationController = viewController as? UINavigationController
  5. self.applyColorFromNavigationController(secondaryNavigationController, toNavigationController: navigationController)
  6. }
  7. }
  8. private func applyColorFromNavigationController(fromVC: UINavigationController?, toNavigationController toVC: UINavigationController) {
  9. toVC.navigationBar.titleTextAttributes = fromVC?.navigationBar.titleTextAttributes
  10. toVC.navigationBar.tintColor = fromVC?.navigationBar.tintColor
  11. }
  12. }

辅助函数applyColorFromNavigationController:toNavigationController函数中的fromVC如果传nil,则toVC.navigationBar的titleTextAttributes和tintColor均会被置为nil,效果相当于重置为系统默认样式。
此处选择在UINavigationControllerDelegate的navigationController:willShowViewController:animated函数中设置样式。该函数在合并和展开时都会被调用。viewController参数就是即将要成为topViewController的view controller。
当然也可以在UISplitViewControllerDelegate中设置,只是这样实现会稍麻烦。

后记:

第一次写近似教程的笔记,感觉不太自然,文章结构也乱七八糟,不晓得别人能不能看得懂。希望这些文章能帮到其他在自学路上奋斗的人吧。我会再努力,争取写得像样一点 ^_^

(不晓得用Cmd Markdown写的东西别人能不能评论呢?)

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注