I think one of the most elegant (and protocol oriented) ways to do this would be with a UIViewControllerTransitioningDelegate
extension. Extend the protocol and provide a default implementation for animationController(forPresented: presenting: source:)
and 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:
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. 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.
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
:
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. Good luck!