了解 UIViewController 转换的价值

Understanding the value of UIViewController transitions

我正在尝试学习一些新的 iOS 编程模式。我已经阅读了很多关于 iOS 7 中添加的 UIViewController 转换 API 的内容。它们看起来很酷,但对于看起来更简单的任务来说也感觉很沉重。

考虑这个用例: 我有一个管理 "slides" 的自定义容器视图控制器。它包含一组幻灯片视图控制器,用户可以通过点击按钮在它们之间前后移动。

我可以按如下方式实现转换:

private func transitionToViewController(viewController: UIViewController, direction: TransitionDirection = .Forward, animated: Bool = true) {
    currentViewController.willMove(toParentViewController: nil)
    addChildViewController(viewController)
    // ... set up frames, other animation prep ...
    contentContainerView.addSubview(comingView)
    UIView.animate(duration: 0.5, animations: { 
        // do the animations
    }) { (finished) in
        leavingView.removeFromSuperview()
        self.currentViewController.removeFromParentViewController()
        viewController.didMove(toParentViewController: self)
        // final clean up
    } 
}

较新的转换 API 将如何改进这一点?据我了解,如果您滚动自己的容器视图控制器,这些 API 使用起来会更加复杂(请参阅 custom-container view controller transitions.

转换 API 中的值主要用于交互式转换吗?

感谢您的澄清

我认为新的转换 API(UIViewControllerTransitioningDelegate 和朋友)只是控制器之间视图转换泛化的最后一步。

在 UIKit 的第一个版本中,我们必须 hack the system transition code to get any custom transitions at all. Years later we got controller containment that made it possible to manage view controllers as first-class citizens and create our own interactive transitions。最后一步是拥有一个功能齐全的通用系统 API 来实现您梦寐以求的任何转换——这就是新的转换 API。

新的 API 可以将转换提取到独立的 classes 中。反过来,最终可以从 GitHub 下载一个转换库并将其作为简单的转换委托插入到您现有的代码中。无需从某些特定的 superclass 派生视图控制器,无需使用第三方控制器容器,无需向 UIKit classes 添加扩展。现在,转换终于成为 UIKit 中的第一个 class 公民。

How would the newer transitioning APIs improve this?

TL;DR 通过封装实现可维护性、可重用性、可测试性。

封装:评论表明有逻辑来设置和状态来跟踪动画。您的视图控制器可能已经足够大了;将转换逻辑放在其他地方会使每个部分更小,因此更易于维护。

可重用性:在此之后您接下来要做的事情是什么?毫无疑问,设置从转换到控制器的转换。而且有没有可能是这部动画的反转?很有可能。因此,您可能会将此代码复制并粘贴到该控制器并在那里反转它。现在你有两个副本。使用转换的副本将更易于维护。 (另请注意 pods 自定义转换的存在,因为可重用性和可共享性齐头并进。)

可测试性: 众所周知,嵌入在重量级视图控制器中的代码很难测试。可以在没有实时视图状态开销的情况下单独测试自定义转换。

因此,对于您打算多次查看的任何代码,转换 API 可能值得付出努力!