10

I'm working on an app which uses Facebook integration, and the log in system works fine now. However, I can't seem to return to my initial view controller when the user clicks log out.

Here's an overview of my storyboard:

Screenshot of storyboard

I would like to return to the start when the user clicks the blue button (on the top). What would I do to achieve that? As you can see I have multiple Navigation Controllers, and I only use Push-seguesto get there. However, I do use the SWRevealViewController, which you can see in the middle.

I've tried [self.navigationController popToRootViewControllerAnimated:YES]; which doesn't do anything.

Any advice? Anyone familiar with the SWRevealViewController and what it might have done to my Navigation stack? Any help will be appreciated!

Thanks.

Aleksander
  • 2,735
  • 5
  • 34
  • 57

7 Answers7

9

Try this,

UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"NameOfYourStoryBoard" 
                                                     bundle:nil];
LoginViewController *add = 
           [storyboard instantiateViewControllerWithIdentifier:@"viewControllerIdentifier"];

[self presentViewController:add 
                   animated:YES 
                 completion:nil];
Ramdhas
  • 1,765
  • 1
  • 18
  • 26
  • That did the trick, but when I get back to the login screen and press the login-button (which is just standard Facebook, no changes there), I get 10s of these in the console: `CGContextSetFillColorWithColor: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.`. Can you figure it out? – Aleksander Mar 29 '14 at 08:34
  • @Alekplay - I've seen those kinds of issues when using third party libraries or sometimes on older (beta) versions of Xcode. If you have any third party libs you might want to reach out to get the latest version or upgrade the Xcode. BTW - Latest version of Xcode has some of these quirks as well but they do not translate to the app (normally). Naturally mileage may vary as your situation may be different. – Tommie C. Mar 29 '14 at 17:35
  • 1
    I'm not sure this is a good solution. What you're doing is creating another UI stack on top of your existing stack. If the user does this multiple times the stack gets larger and larger and you'll run out of memory. Plus there can be other side-effects of many stacked VCs all on top of each other. – Sherwin Zadeh Jun 08 '18 at 04:21
2

First of all, I don't think you need that many UINavigationControllers. Using only one in your application should be enough. The reason popToRootViewController is not working in your case is because it will go to the first view controller withing a UINavigationController. You have nested many UINavigationControllers, thus when you click the blue button in the settings view controller it will go to the sidebar view controller (can't read it properly, the image is small).

You can do the following to get to the root view controller of your app:

UINavigationController *rootController =[(UINavigationController*)[(AppDelegate*)
        [[UIApplication sharedApplication]delegate] window] rootViewController]];

Replace AppDelegate with however it's called in your app.

But my advice is to remove all intermediate UINavigationControllers. Then just doing popToRootViewController should do the trick.

Matías R
  • 2,195
  • 1
  • 14
  • 12
  • I assume you missed a `]` there, so I added it where Xcode suggested. Here's what I have `UINavigationController *rootController =[[(UINavigationController*)[[(XYZAppDelegate*) [[UIApplication sharedApplication]]delegate] window] rootViewController];`. But I get an error saying **Expected Identifier**. Do you have a solution? – Aleksander Mar 29 '14 at 08:30
2

Write Below Method in root viewcontroller

- (IBAction)returnToDashboard:(UIStoryboardSegue *)segue;

Give segue connection to destination view controller like below see in image

Give identifier to segue and assign method to that segue

Like below image

use below method in destination view controller

 [self performSegueWithIdentifier:@"pushtoDashboard" sender:self];
Muralikrishna
  • 1,044
  • 10
  • 17
2

Problem

You'd like to return from a view controller (source) to the start (a destination view controller) when the user clicks the blue button (on the top)

Recommendation

I recommend you take a quick look at the highly rated SO answer which demonstrates how to use the unwind segue (that's the little green exit box on your view controller in the storyboard). Unwind segues are the modern way of accomplishing your goal, but you can also call dismissViewController:animated from the source controller. You should also take a quick read of a very small Apple note (TN2298) on using the unwind segue.

Essentially you will want to add the following method to your destination view controller:

- (IBAction)unwindToMainMenu:(UIStoryboardSegue*)sender
{
}

Then use ctrl+drag and click from the blue button down to the green exit icon on the source view controller. This will popup a menu and you can select unwindToMainMenu from the list. You will need to give the new segue an identifier in the Identity Inspector (e.g. segueToMain).

Manual Unwind

The technical note above (TN2298) will also show you how you can create a manual unwind segues that may be called programmatically (similar to how one might say performSegueWithIdentifier...).

Manual Unwind

Community
  • 1
  • 1
Tommie C.
  • 12,895
  • 5
  • 82
  • 100
1

I was working on a very similar problem. I am using a storyboard with a navigation controller & implemented the highly recommended SWRevealViewController, with iOS 7 & Xcode 5.1. I tried unsuccessfully to implement some of the solutions mentions. Either the screen didn't change or I got blank table. I used a hybrid version of the programatic examples provided in SWRevealController & other answers here to get a working solution. I added this as apart of my login button action

UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
InboxTableViewController *viewController = [storyBoard instantiateViewControllerWithIdentifier:@"inbox"];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:viewController];
[self.revealViewController pushFrontViewController:nav animated:YES];

I retrieved my storyboard & initiated the view controller I wanted from the storyboard & then added to a navigation controller. Finally I used the SWRevealViewController method to Push the view I desired to the front.

urbankid78
  • 11
  • 2
1

I'm using swift and what worked for me was this:

var loginVC: UIViewController? = self.storyboard?.instantiateViewControllerWithIdentifier("UILogin") as?    UIViewController

self.presentViewController(loginVC!, animated: true, completion: nil)
Lvkz
  • 946
  • 14
  • 20
  • 1
    Your code worked but I had to modify it a bit for swift 2, looks like this now, let loginVC: UIViewController? = self.storyboard?.instantiateViewControllerWithIdentifier("loginWindow") self.presentViewController(loginVC!, animated: true, completion: nil) – Joseph Astrahan Mar 28 '16 at 06:38
  • 1
    I'm not sure this is a good solution. What you're doing is creating another UI stack on top of your existing stack. If the user does this multiple times the stack gets larger and larger and you'll run out of memory. Plus there can be other side-effects of many stacked VCs all on top of each other. – Sherwin Zadeh Jun 08 '18 at 04:23
1

When you have different storyboards simply "presenting" the required VC from the initial storyboard does the trick:

Swift 3

if let loginVC = UIStoryboard(name: "Login", bundle: nil).instantiateInitialViewController() {
   present(loginVC, animated: true, completion: nil)
}

In some cases there might be leaking UITransitionView's. You might remove them right after the "presenting" code, but not before it and not in it's completion:

if let subviews = UIApplication.shared.keyWindow?.subviews,
    let transitionViewClass = NSClassFromString("UITransitionView") {
    for subview in subviews where subview.isKind(of: transitionViewClass) {
        subview.removeFromSuperview()
    }
}

<– This works as of Xcode 8.2.1 and iOS 10.2 but no guarantee if will work forever. Be careful with it.

Vitalii
  • 4,267
  • 1
  • 40
  • 45