简体   繁体   English

UIViewController的默认自定义转换

[英]Default Custom Transition for UIViewController

I am developing a library and I want to provide a default custom transition between two view controllers, the user can also provide his own implementation the first idea that comes to my my mind is to override UIViewController and implement the UIViewControllerTransitioningDelegate and then users can subclass my CustomTransitionViewController is it the best way to do it ? 我正在开发一个库,我想在两个视图控制器之间提供一个默认的自定义转换,用户也可以提供自己的实现,我想到的第一个想法是覆盖UIViewController并实现UIViewControllerTransitioningDelegate然后用户可以继承我的CustomTransitionViewController是最好的方法吗? any limitations ? 任何限制? is there a more elegant way using just protocols for example with default implementation ? 是否有一种更优雅的方式只使用协议,例如默认实现?

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)
  }
}

I think one of the most elegant (and protocol oriented) ways to do this would be with a UIViewControllerTransitioningDelegate extension. 我认为最优雅(和面向协议)的方法之一是使用UIViewControllerTransitioningDelegate扩展。 Extend the protocol and provide a default implementation for animationController(forPresented: presenting: source:) and animationController(forDismissed:) . 扩展协议并为animationController(forPresented: presenting: source:)animationController(forDismissed:)提供默认实现。 The extension would look something like this: 扩展名看起来像这样:

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)
    }
}

And then tell your users to extend their view controllers to conform to this protocol. 然后告诉用户扩展他们的视图控制器以符合此协议。 Since you already implemented the only requirements in a protocol extension, all they need to do is add the conformance declaration, like so: 由于您已经在协议扩展中实现了唯一的要求,所以他们需要做的就是添加一致性声明,如下所示:

class MyViewController: UIViewController, UIViewControllerTransitioningDelegate { }

If you want to extend all UIViewController s to do so, you can do it with an empty extension: 如果要扩展所有UIViewController ,可以使用空扩展:

extension UIViewController: UIViewControllerTransitioningDelegate { }

That should work. 这应该工作。 In my opinion, it's a very clean, elegant solution that doesn't require unnecessary subclassing. 在我看来,这是一个非常干净,优雅的解决方案,不需要不必要的子类。 It also makes it easy to provide different implementations of animationController(forPresented: presenting: source:) and animationController(forDismissed:) in each view controller. 它还可以轻松地在每个视图控制器中提供animationController(forPresented: presenting: source:)animationController(forDismissed:)不同实现。 Your users can just add their own implementations of the two aforementioned functions wherever they want. 您的用户只需在任何他们想要的地方添加他们自己的两个上述功能的实现。 Also, you don't need to deal with messy Objective C stuff like associated objects. 此外,您不需要像关联对象那样处理凌乱的Objective C之类的东西。

If you're providing this functionality in some sort of prepackaged bundle and you want to hide the underlying implementation, you could declare your own protocol, make it a subprotocol of UIViewControllerTransitioningDelegate , extend it similarly, and have your users conform to your custom protocol instead of UIViewControllerTransitioningDelegate : 如果您在某种预先打包的捆绑包中提供此功能,并且您希望隐藏底层实现,则可以声明自己的协议,使其成为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 { }

Whichever route you take, this solution gives you what you want without making you deal with extraneous subclassing or ugly Objective C concepts. 无论您采用哪种方式,此解决方案都可以为您提供所需的内容,而无需处理无关的子类或丑陋的Objective C概念。 Good luck! 祝好运!

You could also just make an extension for the UIViewController that does all the things you need and additionally conforms to your protocol, that enables the user to ie disable the default transitions. 您还可以为UIViewController做一个扩展 ,它可以完成您需要的所有操作,并且还符合您的协议,使用户可以禁用 默认转换。

As an example: 举个例子:

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
}

How to add stored properties to extensions , you could have a look at this . 如何将存储的属性添加扩展 ,您可以看看这个

All of this, if you can find a way to set the transitioningDelegate somehow in the extension , otherwise you'll have to subclass . 所有这一切,如果你能找到一种方法在扩展中以某种方式设置transitioningDelegate ,否则你将不得不进行子类化

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM