UIViewController的默认自定义转换

iOS*_*eek 7 uiviewcontroller ios swift 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)
  }
}
Run Code Online (Sandbox Code Playgroud)

pra*_*jal 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)
    }
}
Run Code Online (Sandbox Code Playgroud)

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

class MyViewController: UIViewController, UIViewControllerTransitioningDelegate { }
Run Code Online (Sandbox Code Playgroud)

如果你想扩展所有UIViewControllers来做,你可以用一个空的扩展名来做:

extension UIViewController: UIViewControllerTransitioningDelegate { }
Run Code Online (Sandbox Code Playgroud)

这应该工作.在我看来,这是一个非常干净,优雅的解决方案,不需要不必要的子类.它也可以很容易地提供的不同实现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 { }
Run Code Online (Sandbox Code Playgroud)

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


Mik*_*sep 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
}
Run Code Online (Sandbox Code Playgroud)

如何向扩展添加存储属性,你可以看看这个

transitioningDelegate所有这一切,如果你能找到一种方法在扩展中以某种方式设置,否则你将不得不子类化