How to pop thirdviewcontroller to firstviewcontroller in singleview app - ios

In my app I have three uiviewcontroller: firstviewcontroller, secondviewcontroller and thirdviewcontroller.
I go from firstviewcontroller to secondviewcontroller using navigationcontroller and then from secondviewcontroller to thirdviewcontroller
I want go back from thirdviewcontroller to fristviewcontroller.

use below code:
[self.navigationController popToRootViewControllerAnimated:YES];
also for moving to any particular viewController which is in navigation hierarchy you can use below code:
[self.navigationController popToViewController:<#(UIViewController *)#> animated:<#(BOOL)#>];

- (IBAction)GoFirstView:(id)sender
{
for (UIViewController *controller in self.navigationController.viewControllers)
{
if ([controller isKindOfClass:[Firstviewcontroller class]])
{
//Do not forget to import Firstviewcontroller.h
[self.navigationController popToViewController:controller animated:YES];
break;
}
}
}

Related

MMDrawerController where I need to add sidemen buttons?

I am junior iOS dev and trying to use MMDrawerController.
I have MainStoryboard with 4 views.
NavigationController (embed on CenterViewController controller)
CenterViewController
LeftViewController
AboutViewController
I've added button on Navigation left item on CenterViewController and tap on it open/close my sidemenu.
But if I wan't to change center view with this code
ViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier:#"AboutViewController"];
if (vc)
[appDelegate.drawerController setCenterViewController:vc withCloseAnimation:YES completion:nil];
It works fine but I have no navigation left button. Why?
Thanks
My solution is:
AboutViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier:#"AboutViewController"];
if (vc)
{
if ( [appDelegate.drawerController.centerViewController isKindOfClass:[UINavigationController class]] )
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
UINavigationController *navController = (UINavigationController *)appDelegate.drawerController.centerViewController;
[appDelegate.drawerController toggleDrawerSide:MMDrawerSideLeft animated:YES completion:nil];
[navController pushViewController:vc animated:YES];
}
}

Navigation Back shows other Viewcontroller during the transition

I have three Viewcontrollers : ViewControllerA, ViewControllerB and ViewControllerC.
When I am in ViewControllerC, I click on Navigation Back button to go back to ViewControllerA directly, skipping ViewControllerB.
I have tried following approaches, both of them work. But, I wonder while transiting from ViewController C to ViewController A, it shows ViewController B in one second for during the transition.
Is there a way just directly navigate from ViewController C to ViewController A skipping ViewControllerB.
Approach 1:
-(void) viewWillDisappear:(BOOL)animated {
if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound) {
NSLog(#"back button pressed");
[self.navigationController popViewControllerAnimated:YES];
}
[super viewWillDisappear:animated];
}
Approach 2:
-(void) viewWillDisappear:(BOOL)animated {
if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound) {
NSLog(#"back button pressed");
//[self.navigationController popViewControllerAnimated:YES];
NSMutableArray *allViewControllers = [NSMutableArray arrayWithArray:[self.navigationController viewControllers]];
for (UIViewController *aViewController in allViewControllers) {
if ([aViewController isKindOfClass:[ViewControllerA class]]) {
[self.navigationController popToViewController:aViewController animated:NO];
}
}
}
[super viewWillDisappear:animated];
}
You need to use setViewControllers method, and pass only the viewControllerA that is the first element in your navigationController.viewControllers array
Code
- (IBAction)backAction:(id)sender {
UIViewController * viewControllerA = [self.navigationController.viewControllers firstObject]; //we get the first viewController here
[self.navigationController setViewControllers:#[viewControllerA] animated:YES];
}
similar answer here How to start from a non-initial NavigationController scene but in swift
Try popToRootViewControllerAnimated . It will move to First ViewController which NavigationController embed.
[self.navigationController popToRootViewControllerAnimated:YES];
NSArray *arrayViewControllers = [self.navigationController viewControllers];
for (UIViewController *viewcontroller in arrayViewControllers) {
if ([viewcontroller isKindOfClass:[ViewControllerA class]]) {
[self.navigationController popToViewController:viewcontroller animated:true];
}
}

Pop to particular controller on iOS | Objective-c

I have the following code to push new ViewControllers.
- (IBAction)btnEditPressed:(id)sender {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *controller = [storyboard instantiateViewControllerWithIdentifier:#"contactListViewController"];
[self parentShowViewController:controller sender:sender];
}
- (void)parentShowViewController:(UIViewController *)controller sender:(id)sender {
if ([self isIOS7]) {
// En iOS7 no existe el método showViewController
[self.navigationController pushViewController:controller animated:YES];
} else {
//[self.navigationController pushViewController:controller animated:YES];
[super showViewController:controller sender:sender];
}
}
Now I have the following scenario: I have 3 ViewControllers called A,B,C.
A->B->C If press back button I want to back from C to A
Try something like this
If you want go to Controller A from controller C on Controller C create custom back button and set the action of it, and put the following code.
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:0] animated:YES];
This is only work if you know that Controller A is your first Controller in Navigation.
If you don't know the order of viewController try this one
for (UIViewController *vc in self.navigationController.viewControllers) {
if ([vc isKindOfClass:[ViewControllerA class]]) {
[self.navigationController popToViewController:VC animated:Yes];
}
}
And to add a custom button go to this link
Hope this will help you.

Hide LoginViewController or dismiss to parentView

This is a normal LoginView calling on a specific action in my app
sourceViewVontroller
if ([password length] == 0) {
loginViewController *seatView = [mainStory instantiateViewControllerWithIdentifier:#"loggingView"];
[self presentViewController:login animated:YES completion:nil];
}
it checks if user not signed in yet when he's calling this action, so it redirects him to the loginViewController, then
loginViewController
UIStoryboard *mainStory = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
DestinationViewController *Dest = [mainStory instantiateViewControllerWithIdentifier:#"destView"];
[self presentViewController:Dest animated:YES completion:nil];
it goes to the destinationView that needs a login, now my problem is how to go back (dismiss not presentmodalView) to the sourceViewController, or simply, how to remove the loginViewController from the queue on success and dismiss directly to the source?
destinationViewController
// Tried to use presentView .. but i dont need to reload sourceView, just dismiss to it !
//[self presentViewController:srcView animated:YES completion:NULL];
//This is what am doing ..
[self dismissViewControllerAnimated:NO completion:nil];
Or just let me know if there is other professional way to do this login flow
I suggest for you another way:
First in - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
You will check user login or not. If login you will set rootView to destinationViewController. If not set rootView to loginViewController
SampleCode:
UIStoryboard *mainStory = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
if (logged) {
DestinationViewController *Dest = [mainStory instantiateViewControllerWithIdentifier:#"destView"];
self.window.rootViewController = Dest;
} else {
LoginViewController *seatView = [mainStory instantiateViewControllerWithIdentifier:#"loggingView"];
self.window.rootViewController = seatView;
}
When logout you just call notification or delegate set rootViewController of window to loginViewController.
Do not use presentViewController for bringing login controller.
Complete Process :
In Singleton class. set a global property.
#property (assign)BOOL isUserLoggedIn;
When user logs in or logs out, set this variable to true or false.
Set an enum in LoginViewController.
typedef enum {
DestViewControllerOne =1,
DestViewControllerTwo
} SignInType;
In this enum, put all your view controller where you wanna put that login check.
Set a property in login view controller to hold source controller value -
#property (nonatomic, assign) NSInteger signInType;
Set up a delegate in login controller to redirect after successfull login -
#protocol SignInProtocolDelegate <NSObject>
#optional
-(void) signInSuccess:(NSInteger) signInType;
#end
Create a property with that delegate in login controller -
#property (nonatomic, assign) NSObject<SignInProtocolDelegate>* delegate;
Now before proceeding to required view controller, perform below check -
if(![[TESingleton shareData] isUserLoggedIn]){
[self funcNavigateToSignInWithAlert:YES withSignInType:proceedToDestViewControllerOne];
}
else
{
[self proceedToDestViewControllerOne];
}
-(void)funcNavigateToSignInWithAlert:(BOOL)showAlert withSignInType:(NSInteger) signIntype
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:STORYBOARDNAME bundle:nil];
LoginViewController *viewController = (LoginViewController *)[storyboard instantiateViewControllerWithIdentifier:#"LoginViewController"];
[viewController setSignInType:signIntype];
[viewController setDelegate:self];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewController];
navController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[[SlideNavigationController sharedInstance] presentViewController:navController animated:YES completion:nil];
}
By this, it will bring login page.
Next -
After successfull login, Do this in login controller :
[self dismissViewControllerAnimated:YES completion:nil];
[[self delegate] signInSuccess:self.signInType];
Import login delegate method in source controller that we have written above -
-(void) signInSuccess:(NSInteger) signInType
{
switch (signInType)
{
case DestViewControllerOne:
[self performSelector:#selector(proceedToDestViewControllerOne) withObject:nil afterDelay:0.5];
break;
case DestViewControllerTwo:
[self performSelector:#selector(proceedToDestViewControllerTwo) withObject:nil afterDelay:0.5];
break;
default:
break;
}
}
Implement these methods in source view controller -
-(void) proceedToDestViewControllerOne
{
//Restricting navigation to signin
//Addded by vikas Jul 8,2015
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:STORYBOARDNAME bundle:nil];
DestViewcontrollerOne *objDestViewcontrollerOne = (DestViewcontrollerOne *)[storyboard instantiateViewControllerWithIdentifier:#"DestViewcontrollerOne"];
[self.navigationController objDestViewcontrollerOne animated:YES];
}
This is complete process.
Use Unwind Segues
Add a method in SourceViewController
For Swift
#IBAction func unwindToThisViewController(segue: UIStoryboardSegue) {
}
For Objective-C
- (IBAction)unwindToThisViewController:(UIStoryboardSegue *)unwindSegue {
}
You can come back to the SourceViewController in two ways.
Using Storyboard e.g when an UIButton action fires.
Using performSegueWithIdentifier in code.
Storyboard:
Control drag form an UIButton in DestinationViewController to Exit segue inSourceViewController
In Code:
Control drag form an UIButton in DestinationViewController to Exit segue inSourceViewController
Call performSegueWithIdentifier:#"ExitToSourceViewController" when need to come back to SourceViewController

iOS use the delegate pass value not trigger the method

I was test the delegate pass the value in objective-c.
I know there are other methods can pass string between UIViewControllers like NSNotifyCenter..etc.
Now I want to try to use the delegate pass value .
But I encounter some problems.
I use the navigation and there have two UIViewController(FirstUIViewcontroller and SecondUIViewController).
Now I want to use manual to change to SecondUIViewController,not use the button drag to the SecondUIViewController at FirstUIViewController.
So I add the code in the FirstUIViewController.m button action.
- (IBAction)pushBtnAction:(id)sender {
SecondViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
[self.navigationController pushViewController:controller animated:YES];
}
Then I want to pass the value from the SecondUIViewcontroller when I pop the view controller.
So I add the delegate implement and se the delegate in the FirstUIViewController.m.
- (void)viewDidLoad {
[super viewDidLoad];
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
secondVC = (SecondViewController*)[mainStoryboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
secondVC.delegate = self;
}
-(void) passSecondVC:(SecondViewController *)vc didAddValue:(NSString *)str
{
NSLog(#"second str:%#",str);
}
In the SecondUIViewController.h , I had declare delegate method.
#class SecondViewController;
#protocol SecondViewControllerDelegate <NSObject>
#optional
-(void)passSecondVC:(SecondViewController*)vc didAddValue:(NSString*) str;
#end
#interface SecondViewController : UIViewController
#property (nonatomic,assign) id<SecondViewControllerDelegate> delegate;
- (IBAction)passValueDelegatBtnAction:(id)sender;
In the SecondViewController.m ,
when I click the button will pop self uiviewcontroller and pass the value to FirstUIViewController.
- (IBAction)passValueDelegatBtnAction:(id)sender {
if( [self.delegate respondsToSelector:#selector(passSecondVC:didAddValue:)])
{
[self.delegate passSecondVC:self didAddValue:#"this is string from sencond vc"];
}
[self.navigationController popViewControllerAnimated:YES];
}
(My problems)
But in this status , I always can't get the value in the delegate method in the FirstUIViewController.
I had try to other method like below in the FirstViewController.m
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog(#"segue");
id vc = segue.destinationViewController;
if( [vc isKindOfClass:[SecondViewController class]])
{
SecondViewController *secondVC = vc;
secondVC.delegate = self;
}
}
There are same problem.
I can't get the value from the delegate method.
Have anyone know where the problems?
I post my completely code in here.
Thank you very much.
Alright!
Remove your code from the viewDidLoad: method and set the delegate when you push the secondViewController.
- (IBAction)pushBtnAction:(id)sender {
SecondViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
[controller setDelegate:self];
[self.navigationController pushViewController:controller animated:YES];
}
So what was going wrong?
Ans: You create a new object in your viewDidLoad: method and set your firstViewController as delegate to it. Now while pushing you are creating another object of SecondViewController whose delegate is not set.
I downloaded your code & fixed it.
You don't want this line. so comment it,
// UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
// secondVC = (SecondViewController*)[mainStoryboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
// secondVC.delegate = self;
Edit this method as below,
- (IBAction)pushBtnAction:(id)sender {
SecondViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
controller.delegate = self;
[self.navigationController pushViewController:controller animated:YES];
}
Also edit this method as below,
- (IBAction)passValueDelegatBtnAction:(id)sender {
// if( [self.delegate respondsToSelector:#selector(passSecondVC:didAddValue:)])
// {
[self.delegate passSecondVC:self didAddValue:#"this is string from sencond vc"];
// }
[self.navigationController popViewControllerAnimated:YES];
}
you forgot some code in pushBtnAction..
- (IBAction)pushBtnAction:(id)sender {
SecondViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"]; // It's different to VC you init in viewDidLoad
controller.delegate = self; // you forgot....
[self.navigationController pushViewController:controller animated:YES];
}
prepareForSegue be call when you use segue to navigation.

Resources