Faking a Push Segue (Objective-C)
Recently I was approached with a cool challenge. I needed to come up with a way to "fake" a push animation, forward and backward. Usually you use transitions provided (for free) with Modal or Push segue but this needed to be a push animation with no NavigationBar and no hidden NavigationBar, basically this is impossible to do without a NavigationBar unless you use a Custom Segue which I found pretty easy to implement and opens the door to a lot of new and cool transitions that could make your App unique!
Let's create a "Fake" Push Segue:
We'll do something very simple but that shows you how to create a custom segue, I find that making something really simple makes learning much better.
- Create a New Project. Single View Template.
- Add a New Class (File -> New -> File: Cocoa Touch: Objective-C Class):
Class: MyCustomSeguePushForward
Subclass of: UIStoryboardSegue
Since we need a custom animation to "Go Back" repeat step 2 but with this new information:
Class: MyCustomSeguePushBackward
Subclass of: UIStoryboardSegue
Go to the Storyboard and add one more ViewController (You should have 2 ViewControllers) on the storyboard. Drag a UIButton to one of the Storyboard and from that UIButton create a Segue to the second ViewController. (Right Click from button to second storyboard and let go, or Control + Click). When you create a Segue in your storyboard you have 3 options: Modal, Push or Custom. Create a Custom Segue. Next you need to Select the Segue and under the "Segue Class" type or custom class name: MyCustomSeguePushForward.
On the second (destination) ViewController you need to repeat the steps so we can go back to the original ViewController: Create a button, then create a Custom Segue but this time use the class name: MyCustomSeguePushBackward
- Now we will Override the “perform” method to achieve what we want. Open MyCustomSeguePushForward.m and create a method called perform with the following code:
-(void) perform {
UIView *preV = ((UIViewController *)self.sourceViewController).view;
UIView *newV = ((UIViewController *)self.destinationViewController).view;
UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
newV.center = CGPointMake(preV.center.x + preV.frame.size.width, newV.center.y);
[window insertSubview:newV aboveSubview:preV];
[UIView animateWithDuration:0.4
animations:^{
newV.center = CGPointMake(preV.center.x, newV.center.y);
preV.center = CGPointMake(0- preV.center.x, newV.center.y);}
completion:^(BOOL finished){
[preV removeFromSuperview];
window.rootViewController = self.destinationViewController;
}];
}
- Since the method to go back is almost the same I asked my friend Vivek Vasani for some help since my brain wasn't working 100%. Together we were able to reverse the code and make the "Push Back" animation. Open MyCustomSeguePushBackward.m and write the following method:
-(void) perform {
UIView *preV = ((UIViewController *)self.sourceViewController).view;
UIView *newV = ((UIViewController *)self.destinationViewController).view;
UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
newV.center = CGPointMake(preV.center.x - preV.frame.size.width, newV.center.y);
[window insertSubview:newV aboveSubview:preV];
[UIView animateWithDuration:0.4
animations:^{
newV.center = CGPointMake(preV.center.x, newV.center.y);
preV.center = CGPointMake(preV.center.x + preV.frame.size.width, newV.center.y);}
completion:^(BOOL finished){
[preV removeFromSuperview];
window.rootViewController = self.destinationViewController;
}];
}
That's it! Here’s the source code for the finished project: https://github.com/rfunk82/CustomSegue
Written by Ricardo Funk
Related protips
1 Response
Hey there!
This is really good segue! I'm using it in my app --> BUT !
You have a seriouse bug in it.
The viewDidLoad of the destenation controller is called twice! i really dont know why but if you know the answer.. please let me know!