UIViewController的默认自定义转换

时间:2016-12-18 19:29:41

标签: ios swift uiviewcontroller swift-protocols

我正在开发一个库,我想在两个视图控制器之间提供默认的自定义转换,用户也可以提供自己的实现,我想到的第一个想法是覆盖UIViewController并实现UIViewControllerTransitioningDelegate然后用户可以继承我的CustomTransitionViewController这是最好的方法吗?任何限制?是否有一种更优雅的方式只使用协议,例如默认实现?

import UIKit

class CustomTransitionViewController: UIViewController, UIViewControllerTransitioningDelegate {

  required init?(coder aDecoder: NSCoder) {
      super.init(coder: aDecoder)
      self.transitioningDelegate = self
  }

  override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil:Bundle?)   {
      super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
      self.transitioningDelegate = self
  }

  func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
      return FadeInAnimator(transitionDuration: 0.5, startingAlpha: 0.8)
  }

  func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
      return FadeInAnimator(transitionDuration: 0.5, startingAlpha: 0.8)
  }
}

2 个答案:

答案 0 :(得分:6)

我认为最优雅(以协议为导向)的方法之一是使用UIViewControllerTransitioningDelegate扩展名。扩展协议并为animationController(forPresented: presenting: source:)animationController(forDismissed:)提供默认实现。扩展名看起来像这样:

extension UIViewControllerTransitioningDelegate where Self: UIViewController {
    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return FadeInAnimator(transitionDuration: 0.5, startingAlpha: 0.8)
    }

    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return FadeInAnimator(transitionDuration: 0.5, startingAlpha: 0.8)
    }
}

然后告诉您的用户扩展他们的视图控制器以符合此协议。由于您已经在协议扩展中实现了唯一的要求,他们所需要做的就是添加一致性声明,如下所示:

class MyViewController: UIViewController, UIViewControllerTransitioningDelegate { }

如果您想扩展所有UIViewController以执行此操作,则可以使用空扩展名进行扩展:

extension UIViewController: UIViewControllerTransitioningDelegate { }

那应该有用。在我看来,它是一个非常干净,优雅的解决方案,不需要不必要的子类化。它还可以轻松地在每个视图控制器中提供animationController(forPresented: presenting: source:)animationController(forDismissed:)的不同实现。您的用户只需在任何他们想要的地方添加他们自己的两个上述功能的实现。此外,您不需要处理混乱的Objective C之类的东西,比如关联对象。

如果您在某种预先打包的捆绑包中提供此功能,并且您希望隐藏底层实现,则可以声明自己的协议,使其成为UIViewControllerTransitioningDelegate的子协议,同样地扩展它,以及让您的用户符合您的自定义协议,而不是UIViewControllerTransitioningDelegate

protocol MyProtocol: UIViewControllerTransitioningDelegate {
    //Add your own requirements (if you have any).
}

extension MyProtocol where Self: UIViewController {
    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return FadeInAnimator(transitionDuration: 0.5, startingAlpha: 0.8)
    }

    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return FadeInAnimator(transitionDuration: 0.5, startingAlpha: 0.8)
    }

    //Satisfy your requirements (or let your users do it).
}

class MyViewController: UIViewController, MyProtocol { }

extension UIViewController: MyProtocol { }

无论您采用哪种方式,此解决方案都可以为您提供所需的内容,而无需处理无关的子类或丑陋的Objective C概念。祝你好运!

答案 1 :(得分:0)

你也可以为UIViewController创建一个扩展,它可以完成你需要的所有事情,并且还符合你的协议,使用户可以禁用 默认转换。

举个例子:

protocol ThorsHammer {
    var isDefaultTransitionEnabled: Bool { get set }
}

extension UIViewController: ThorsHammer {
    var isDefaultTransitionEnabled: Bool { /* this part sucks */ }

    // Check if the default transition should happen and
    // do some transition magic
}

如何将存储的属性添加到扩展程序,您可以查看this

所有这一切,如果你能找到一种方法在扩展中以某种方式设置transitioningDelegate,否则你必须继承