I think one of the most elegant (and protocol-oriented) ways to do this would be with the UIViewControllerTransitioningDelegate extension. Extend the protocol and implement the standard implementation for animationController(forPresented: presenting: source:) and animationController(forDismissed:) . The extension will 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) } }
Then ask your users to expand their view controllers to comply with this protocol. Since you have already met the only requirements in the protocol extension, all they need to do is add a conformance declaration, for example:
class MyViewController: UIViewController, UIViewControllerTransitioningDelegate { }
If you want to extend all of the UIViewController to do this, you can do this with an empty extension:
extension UIViewController: UIViewControllerTransitioningDelegate { }
That should work. In my opinion, this is a very clean, elegant solution that does not require an unnecessary subclass. It also makes it easier to provide different implementations of animationController(forPresented: presenting: source:) and animationController(forDismissed:) in each view controller. Your users can simply add their own implementations of the two above functions, wherever they want. In addition, you do not need to deal with dirty Objective-C objects, such as related objects.
If you provide this functionality in some pre-packaged package, and you want to hide the base implementation, you can declare your own protocol, make it a sub- UIViewControllerTransitioningDelegate , extend it similarly and coordinate your users with your user 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 choose, this solution gives you what you want without having to deal with extraneous subclasses or ugly Objective-C concepts. Good luck!