It doesn't matter if it is xib or storyboard that you are using. Normally, the right to left transition is used when you push a view controller into presentor's UINavigiationController.
UPDATE
Added timing function kCAMediaTimingFunctionEaseInEaseOut
Sample project with Swift 4 implementation added to GitHub
Seems like the animated parameter in the presentViewController method doesn't really matter in this case of custom transition. It can be of any value, either true or false.
I have a better solution that has worked for me if you want to mantain the classic animation of Apple, without see that "black" transition that you see using CATransition(). Simply use popToViewController method.
You can look for the viewController you need in
self.navigationController.viewControllers // Array of VC that contains all VC of current stack
You can look for the viewController you need by searching for it's restorationIdentifier.
BE CAREFUL: for example, if you are navigating through 3 view controllers, and when arrive to the last you want to pop the first. You will lose, in this case, the refer to the effective SECOND view controller because the popToViewController has overwritten it. BTW, there's a solution: you can easily save before the popToViewcontroller, the VC you will need later. It worked for me very well.
If you do want to use the "quick fix" CATransition method....
class AA: UIViewController
func goToBB() {
let bb = .. instantiateViewcontroller, storyboard etc .. as! AlreadyOnboardLogin
let tr = CATransition()
tr.duration = 0.25
tr.type = CATransitionType.moveIn
tr.subtype = CATransitionSubtype.fromRight
view.window!.layer.add(tr, forKey: kCATransition)
present(bb, animated: false)
bb.delegate, etc = set any other needed values
}
and then ...
func dismissingBB() {
let tr = CATransition()
tr.duration = 0.25
tr.type = kCATransitionReveal // use "Reveal" here
tr.subtype = kCATransitionFromLeft
view.window!.layer.add(tr, forKey: kCATransition)
dismiss(self) .. or dismiss(bb), or whatever
}
All of this is unfortunately not really correct :(
CATransition is not really made for doing this job.
Note you will get the annoying cross fade to black which unfortunately ruins the effect.
Many devs (like me) really don't like using NavigationController. Often, it is more flexible to just present in an ad-hoc manner as you go, particularly for unusual and complex apps. However, it's not difficult to "add" a nav controller.
simply on storyboard, go to the entry VC and click "embed -> in nav controller". Really that's it.
Or, if you prefer
in didFinishLaunchingWithOptions it's easy to add your nav controller in code
you really don't even need to keep the variable anywhere, as .navigationController is always available as a property - easy.
Really, once you have a navigationController, it's trivial to do transitions between screens,
Read up all answers and can't see correct solution. The right way do to so is to make custom UIViewControllerAnimatedTransitioning for presented VC delegate.
So it assumes to make more steps, but the result is more customizable and haven't some side effects, like moving from view together with presented view.
So, assume you have some ViewController, and there is a method for presenting
var presentTransition: UIViewControllerAnimatedTransitioning?
var dismissTransition: UIViewControllerAnimatedTransitioning?
func showSettings(animated: Bool) {
let vc = ... create new vc to present
presentTransition = RightToLeftTransition()
dismissTransition = LeftToRightTransition()
vc.modalPresentationStyle = .custom
vc.transitioningDelegate = self
present(vc, animated: true, completion: { [weak self] in
self?.presentTransition = nil
})
}
presentTransition and dismissTransition is used for animating your view controllers.
So you adopt your ViewController to UIViewControllerTransitioningDelegate:
In that code view controller is presented over current context, you can make your customizations from that point. Also you may see custom UIPresentationController is useful as well (pass in using UIViewControllerTransitioningDelegate)
// Never Easy than this before :)
// you just need to add a Static function for navigation transition
// This Code is recommended for the view controller.
public class CustomNavigation: UIViewController {
public override func loadView() {
super.loadView();
}
public override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
public override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true);
}
public static func segueNavToLeft(view: UIView) {
let transition = CATransition()
transition.duration = 0.3
transition.type = CATransitionType.push
transition.subtype = CATransitionSubtype.fromLeft
transition.timingFunction = CAMediaTimingFunction(name:CAMediaTimingFunctionName.easeInEaseOut)
view.window!.layer.add(transition, forKey: kCATransition)
}
public static func segueNavToRight(view: UIView) {
let transition = CATransition()
transition.duration = 0.3
transition.type = CATransitionType.push
transition.subtype = CATransitionSubtype.fromRight
transition.timingFunction = CAMediaTimingFunction(name:CAMediaTimingFunctionName.easeInEaseOut)
view.window!.layer.add(transition, forKey: kCATransition)
}
}
// simply call in your viewcontroller:
func moveToRight() {
CustomNavigation.segueNavToRight(view: view)
let controller = self.storyboard?.instantiateViewController(withIdentifier: "id") as! YourViewController
let navigationController = UINavigationController(rootViewController: YourViewController)
navigationController.modalPresentationStyle = .fullScreen
self.present(navigationController, animated: false, completion: nil)
}
func moveToLeft() {
CustomNavigation.segueNavToLeft(view: view)
self.dismiss(animated: true, completion: nil)
}