How to POP a viewcontroller with custom back UIbutton? - ios

I am using side drawer menu https://github.com/mutualmobile/MMDrawerController
I cannot come to back with custom UIButton.
- (IBAction)doBackAction:(id)sender {
NSArray *viewControllers=self.navigationController.viewControllers;
for (UIViewController *viewController in viewControllers) {
NSLog(#"%#",NSStringFromClass([viewController class]));
UINavigationController *obj=(UINavigationController *)[self.mm_drawerController centerViewController];
}
UINavigationController *nav =
(UINavigationController *)self.mm_drawerController.centerViewController;
[nav popToRootViewControllerAnimated:NO];
[self.navigationController popViewControllerAnimated:YES];
[self.mm_drawerController closeDrawerAnimated:YES completion:nil];
}
i have tried this also https://github.com/mutualmobile/MMDrawerController/issues/195
I cannot make it work.

You might consider setting a global variable (e.a. on a singleton or in a database) which ViewController you came from with viewDidDissapear:
- (void)viewDidDissapear {
Singleton.lastViewController = [self class];
}
From there you can do this to know where you came from (e.a. an IBAction):
// Set your global variable: `NSString` Singleton.lastViewController
[self presentViewController:[[UIStoryboard storyboardWithName:#"Main_iPad" bundle:nil] instantiateViewControllerWithIdentifier:Singleton.lastViewController] animated:YES completion:nil];
I use this for apps that have custom segues and programmed navigation.

Please try this one. May be its help to you
for (UIViewController *controller in self.navigationController.viewControllers)
{
if ([controller isKindOfClass:[CartVC class]])
{
//Do not forget to import CompareCarsVC.h
// CATransition *transition = [CATransition animation];
// transition.duration = 0.5;
// transition.type = kCATransitionFade;
//
// [self.navigationController.view.layer addAnimation:transition forKey:kCATransition];
[self.navigationController popToViewController:controller
animated:NO];
break;
}
}

Related

Push View from Presented View Controller in iOS

In Short :
How can I PushViewController from Presented ViewController ?
In Brief :
I have MainViewController, In which I have one button on click of button, I am presenting a view called LoginViewController.
On this page (LoginViewController), I again have button, on click of that, I try to push my view controller(called HomeViewController) it doesn't pushes.
Here is my code snippet,
MainViewController.m
- (IBAction)LoginClicked:(id)sender {
LoginViewController *vc = [[LoginViewController alloc] init];
[self presentViewController:vc animated:YES completion:nil];
}
LoginViewController.m
- (IBAction)buttonActionMethodOnLoginView:(id)sender{
NSLog(#"viewControllers %#",APPDELEGATE.nav.viewControllers);
//LoginViewController is not in this array
HomeViewController *obj = [[HomeViewController alloc] init];
[self.navigationController pushViewController:obj animated:YES];
}
But it did not works for me. Also, I printed a stack of view controllers before pushed, but it doesn't have LoginViewController. So, without adding LoginViewController into a stack of view controllers, How can I pushed to HomeViewController from LoginViewController ?
When I getBack from HomeViewController, then LoginViewController should get opened..
Is it possible using doing this single NavigationController?
Note:- Here, I have just taken an example using Login, Home and Main ViewController. But I want that into Other Screens.
hi when you are Presenting you Login view controller Just present a navigationController like:
LoginVC *loginVCObj =[[LoginVC alloc]initWithNibName:#"LoginVC" bundle:nil];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:loginVCObj];
[self presentViewController:nav animated:YES completion:nil];
Now your PresentedViewController is An navigtioncontroller
now you can simply push to your Home VC
HomeViewController *obj = [[HomeViewController alloc] init];
[self.navigationController pushViewController:obj animated:YES];
Hope it will helpful for you
LoginViewController should not be pushed to navigation controller stack. Let me describe below "why".
Our MainViewController should be on the stack - you always want to go back there.
// AppDelegate.m (only if you don't use storyboards, if you do - you don't need to copy this part of code)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// create the window
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.window setBackgroundColor:[UIColor whiteColor]];
[self.window makeKeyAndVisible];
// set view controllers
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:[[MainViewController alloc] init]];
[self.window setRootViewController:navigationController];
}
On specific action show LoginViewController. You don't want the user to be able to tap back and go to MainViewController. Later, you won't want user to go back to LoginViewController. Because of this, you need to present it as modal:
// inside `MainViewController.m`
- (IBAction)myCoolActionToShowLogin:(id)sender {
[self presentViewController:[[LoginViewController alloc] init] animated:YES completion:nil];
}
Now we can see LoginViewController. When user completes the login, dismiss it and present HomeViewController:
// inside `LoginViewController.m`
- (IBAction)myAwesomeActionToShowHome:(id)sender {
UINavigationController *navigationController = (UINavigationController *)[UIApplication.sharedApplication.keyWindow rootViewController];
[navigationController pushViewController:[[HomeViewController alloc] init] animated:YES];
[self dismissViewControllerAnimated:YES completion:nil];
}
NOTES:
As you may notice, myAwesomeActionToShowHome: expects you have navigation controller as your rootViewController. This is working, but should be nicer - you should check if that navigation is in fact navigation controller instead of casting it. Or you may create a delegate or block to push new one. This is the fastest, easiest working solution, which should be improved later.
You really should read: Apple Developer -> "View Controller Programming" documentation, as these are the core fundamentals you should know to develop & design UX correctly.
Here is the working demo sample.
You can't push from a presented view controller. I suggest, you should maintain your navigation hierarchy.
For that, from your MainViewController, you should present LoginViewController and you should pass navigation controller for the MainViewController.
- (IBAction)openLogin:(id)sender {
LoginViewController *loginVC = (LoginViewController *) [self.storyboard instantiateViewControllerWithIdentifier:#"login"];
[loginVC setReferencedNavigation:self.navigationController];
[self presentViewController:loginVC animated:YES completion:nil];
}
Then inside LoginViewController, you should push to HomeViewController like this,
LoginViewController.h
#interface LoginViewController : UIViewController {
UINavigationController *refNavigationController;
}
- (void) setReferencedNavigation:(UINavigationController *)refNavCon;
LoginViewController.m
- (void) setReferencedNavigation:(UINavigationController *)refNavCon {
refNavigationController = refNavCon;
}
- (IBAction)openHome:(id)sender {
[self dismissViewControllerAnimated:YES completion:^{
UIViewController *homeVC = [self.storyboard instantiateViewControllerWithIdentifier:#"home"];
[refNavigationController pushViewController:homeVC animated:YES];
}];
}
By doing this, it will be look like, you're pushing from LoginViewController but in reality you're pushing from MainViewController.
You can customize this approach to maintain animation and UI for this flow.
1) present a navigation controller with itsroot view controller` set as view controller .
- (IBAction)LoginClicked:(id)sender
{
LoginViewController *loginViewController = [LoginViewController alloc] init];
UINavigationController *navController = [UINavigationController alloc] initWithRootViewController:loginViewController];
[self presentViewController:navController animated:YES completion:nil];
}
- (IBAction)buttonActionMethodOnLoginView:(id)sender
{
HomeViewController *obj = [[HomeViewController alloc] init];
[self.navigationController pushViewController:obj animated:YES];
}
Hope it will work for you.
The problem is that LoginViewController has no navigation controller. Then you give it one.
MainViewController.m
Create a UINavigationController, put LoginViewController in to the stack and present the UINavigationController.
- (IBAction)LoginClicked:(id)sender {
LoginViewController *vc = [[LoginViewController alloc] init];
UINavigationController = nav = [[UINavigationController alloc] init];
nav.viewControllers = #[vc];
[self presentViewController:nav animated:YES completion:nil];
}
LoginViewController.m
- (IBAction)buttonActionMethodOnLoginView:(id)sender{
HomeViewController *obj = [[HomeViewController alloc] init];
[self.navigationController pushViewController:obj animated:YES];
}
Dismiss
Call dismissViewControllerAnimated in your MainViewController.
For Swift 3.0
Present your view controller as a new rootViewController
let navController = UINavigationController.init(rootViewController: self.storyboard!.instantiateViewController(withIdentifier: "SignInViewController"))
self.present(navController, animated: true, completion: {})
Now push your view controller from presented view controller
self.show(self.storyboard!.instantiateViewController(withIdentifier: "SignUpViewController"), sender: self)
Create a UINavigationController instance
[[UINavigationController alloc] initWithRootViewController:[[LoginViewController alloc] init]]
Present that navigationController and then push whatever VC you want to.
MainViewController.m
- (IBAction)LoginClicked:(id)sender {
LoginViewController *vc = [[LoginViewController alloc] init];
UINavigationController *loginNav = [[UINavigationController alloc] initWithRootViewController:vc];
[self presentViewController:loginNav animated:YES completion:nil];
}
LoginViewController.m
- (IBAction)buttonActionMethodOnLoginView:(id)sender{
NSLog(#"viewControllers %#",APPDELEGATE.nav.viewControllers);
//LoginViewController is not in this array
HomeViewController *obj = [[HomeViewController alloc] init];
[self.navigationController pushViewController:obj animated:YES];
}
You have to Push from your firstView (MainViewController), but you can use animation same as PresentView and DismissView. Use following code for this :-
For Push (on MainViewController)
LoginViewController *VC = [[LoginViewController alloc]init];
CATransition* transition = [CATransition animation];
transition.duration = 0.3f;
transition.type = kCATransitionMoveIn;
transition.subtype = kCATransitionFromTop;
[self.navigationController.view.layer addAnimation:transition
forKey:kCATransition];
[[[UINavigationController alloc] initWithRootViewController:VC] pushViewController:VC animated:NO];
//[self.navigationController pushViewController:VC animated:NO];
For Pop (on LoginViewController)
CATransition* transition = [CATransition animation];
transition.duration = 0.3f;
transition.type = kCATransitionReveal;
transition.subtype = kCATransitionFromBottom;
[self.navigationController.view.layer addAnimation:transition
forKey:kCATransition];
[self.navigationController popViewControllerAnimated:NO];
Using this code, you can get animation same as Present-Dismiss ViewControllers. Refer this answer for more details.
And after that, you can use your code for Pushing LoginViewController to HomeViewController
Hope, this is what you're looking for. Any concern get back to me. :)
This is very simple code for present view controller and push view controller.
- (IBAction)LoginClicked:(id)sender {
LoginViewController *objLogicVC = [LoginViewController alloc] init];
UINavigationController *navPresent = [UINavigationController alloc] initWithRootViewController:objLogicVC];
[self presentViewController:navPresent animated:YES completion:nil];
}
- (IBAction)buttonActionMethodOnLoginView:(id)sender{
HomeViewController *objHomeVC = [[HomeViewController alloc] init];
[self.navigationController pushViewController:objHomeVC animated:YES];
}
simply put this code in objective c on button action
UIViewController *yourViewControllerName = [self.storyboard instantiateViewControllerWithIdentifier:#"yourViewControllerName "];
[[self navigationController] pushViewController:yourViewControllerName animated:YES];

How To Present A view Controller animated from bottom

I need a Transparent view controller that will come to screen from bottom. I want to see presenting view controller Transparent. I have written this code to present .
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
RatingPopVC *ratingVc = [storyboard instantiateViewControllerWithIdentifier:#"RatingPopVC1"];
[self.navigationController presentViewController:ratingVc animated:YES completion:nil];
RateView.m file-
(void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor clearColor];//[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.8];
}
You need to make a category of UIViewController on Navigation.
Make a method in category for transparency.
Please follow below written code in .h file of category
#interface UIViewController (navigation)
- (void)presentTransparentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion;
#end
Go to .M file of category
#import "UIViewController+navigation.h"
#implementation UIViewController (navigation)
- (void)presentTransparentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion
{
/*
if(SYSTEM_VERSION_LESS_THAN(#"8.0"))
{
[self presentIOS7TransparentController:viewControllerToPresent withCompletion:completion];
} else {
viewControllerToPresent.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self presentViewController:viewControllerToPresent animated:YES completion:completion];
}
*/
// viewControllerToPresent.view.alpha=0.7f;
viewControllerToPresent.view.backgroundColor = [UIColor clearColor];
viewControllerToPresent.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self presentViewController:viewControllerToPresent animated:YES completion:completion];
}
-(void)presentIOS7TransparentController:(UIViewController *)viewControllerToPresent withCompletion:(void(^)(void))completion
{
UIViewController *presentingVC = self;
UIViewController *root = self;
while (root.parentViewController) {
root = root.parentViewController;
}
UIModalPresentationStyle originalStyle = root.modalPresentationStyle;
root.modalPresentationStyle = UIModalPresentationCurrentContext;
[presentingVC presentViewController:viewControllerToPresent animated:YES completion:^{
root.modalPresentationStyle = originalStyle;
}];
}
you can use CATransition
check it out this may help you
CATransition *animation = [CATransition animation];
[animation setDuration:2];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromTop];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
SecondView *sObj=[[SecondView alloc] initWithNibName:#"SecondView" bundle:nil];
[self.navigationController pushViewController:sObj animated:YES];
[[sObj.view layer] addAnimation:animation forKey:#"SwitchToView1"];
Just add below line of code
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
RatingPopVC *ratingVc = [storyboard instantiateViewControllerWithIdentifier:#"RatingPopVC1"];
ratingVc.view.backgroundColor=[[UIColor blackColor] colorWithAlphaComponent:0.5];//you can set alpha value or Clear Color
ratingVc.modalPresentationStyle = UIModalPresentationCurrentContext;//add this line of code
[self.navigationController presentViewController:ratingVc animated:YES completion:nil];
Hope it helps you..!

Push segue custom animation (Navigation controller)

I have this storyboard :
TabBarController : Tab1 > NavigationController > VC1 > VC2 > VC3
// VC1.m
[self performSegueWithIdentifier:#"VC2" sender:self];
// VC2.m
[self performSegueWithIdentifier:#"VC3" sender:self];
I would like the transition between VC1 and VC2 to be a fade animation, but the transition between VC2 and VC3 the default one.
But I have to do a push segue and not modal to keep the benefits of UINavigationController (unless I'm missing something). All the solution I find for this are using presentViewController.
Try using this CATransition
CATransition *transition = [CATransition animation];
transition.duration = 0.3;
transition.type = kCATransitionFade;
[navigationController.view.layer addAnimation:transition forKey:kCATransition];
isPush ? [navigationController pushViewController:viewController animated:NO] : [navigationController popViewControllerAnimated:NO];
If you insist on a segue than I see 2 ways:
1) Use UIViewControllerAnimatedTransitioning protocol and customize the transitions the way U like.
2) Write a custom UIStoryboardSegue
Or perform you own transitions and animations by means of manipulation of controllers and their views and frames smth like:
- (void)transitionToChildViewController:(UIViewController *)toViewController {
UIViewController *fromViewController = ([self.childViewControllers count] > 0 ? self.childViewControllers[0] : nil);
if (toViewController == fromViewController || ![self isViewLoaded]) {
return;
}
UIView *toView = toViewController.view;
[toView setTranslatesAutoresizingMaskIntoConstraints:YES];
toView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
toView.frame = self.privateContainerView.bounds;
[fromViewController willMoveToParentViewController:nil];
[self addChildViewController:toViewController];
[self.privateContainerView addSubview:toView];
[fromViewController.view removeFromSuperview];
[fromViewController removeFromParentViewController];
[toViewController didMoveToParentViewController:self];
}
the last method perhaps is the most tedious.

How to use animateWithDuration: when presenting view controller on iOS 7?

I'm currently using the following code in order to present my view controller.
CATransition* transition = [CATransition animation];
transition.duration = 1;
transition.type = kCATransitionFade;
transition.subtype = kCATransitionFromBottom;
[self.view.window.layer addAnimation:transition forKey:kCATransition];
[self presentViewController:viewController animated:NO completion:nil];
I need to use more complex animation utilizing UIView animateWithDuration method. It is just modal presentation and background view controller should stay there. How can I animate presenting view controller's view?
Update: next version of code :)
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:NULL];
RootViewControllerEx *viewController = (RootViewControllerEx *)[sb instantiateViewControllerWithIdentifier:#"SB_RDVC"];
viewController.transitioningDelegate = self;
viewController.modalPresentationStyle = UIModalPresentationCustom;
[self presentViewController:viewController animated:YES completion:nil];
...
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
...
}
VC in storyboard doesn't have any segue specified, it stays lonely in storyboard :)
You need to use UIModalPresentationCustom as your UIViewController's modalPresentationStyle.
You then need to create a class that conforms to the UIViewControllerTransitioningDelegate and set that your on presentedViewController.
Example
YourViewController *viewController = [[YourViewController alloc] init];
viewController.delegate = self;
viewController.transitioningDelegate = self;
viewController.modalPresentationStyle = UIModalPresentationCustom;
[self.navigationController presentViewController:viewController animated:YES completion:nil];
You must then implement the following method:
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source;
Which returns an object that conforms to a UIViewControllerAnimatedTransitioning protocol, that implements the following method:
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
UIView *inView = [transitionContext containerView];
UIView *toView = [[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey] view];
toView.frame = //CGRectMake(0,0,0,0);
[inView addSubview:toView];
// Use whatever animateWithDuration you need
[UIView animateWithDuration:0.6f delay:0.0f usingSpringWithDamping:0.7f initialSpringVelocity:0.5f options:UIViewAnimationOptionCurveEaseIn animations:^{
// Custom animation here
} completion:^(BOOL finished) {
// IMPORTANT
[transitionContext completeTransition:YES];
}];
}
Always remember to tell the context when a transition is complete, otherwise you'll enter an unstable state.

push uiviewcontroller from presentModalViewController

I Show a view using presentModalViewController. and from this UIView I want to push a UIView using UINavigationController.
I tried below code for this
[self.parentViewController.navigationController
pushViewController:objViewFullScreen
animated:YES];
But it did not works for me. so please can any one suggest how I push a view from ModelViewController.
Thanks
First you have to present your modal view controller inside a navigation controller:
MyViewController *vc = [[MyViewController alloc] initWithNibName:#"MyNib" bundle:nil];
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:vc];
[self presentModalViewController:nc animated:YES];
[vc release];
[nc release];
Then inside MyViewController you can do:
OtherViewController *vc = [[OtherViewController alloc] initWithNibName:#"MyOtherNib" bundle:nil];
[self.navigationController pushViewController:vc animated:YES];
[vc release];
-(void)pushViewControllerWithCustomAnimation:(UIViewController *)newViewController {
newViewController.view.alpha = 0.0f;
[self.view addSubview:newViewController.view];
[UIView animateWithDuration:1
animations:^{
newViewController.view.alpha = 1;
}
completion:^(BOOL fin){
if (fin) {
// finally display the new viewcontroller for real
[self.navigationController pushViewController:newViewController animated:NO];
}
}];
}

Resources