Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Instead of push segue how to replace view controller (or remove from navigation stack)?

I have a small iPhone app, which uses a navigation controller to display 3 views (here fullscreen):

Xcode screenshot

First it displays a list of social networks (Facebook, Google+, etc.):

list screenshot

Then it displays an OAuth dialog asking for credentials:

login screenshot

And (after that, in same UIWebView) for permissions:

permissions screenshot

Finally it displays the last view controller with user details (in the real app this will be the menu, where the multiplayer game can be started):

details screenshot

This all works well, but I have a problem, when the user wants to go back and select another social network:

The user touches the back button and instead of being displayed the first view, is displayed the second one, asking for OAuth credentials/permissions again.

What can I do here? Xcode 5.0.2 shows a very limited choice for segues - push, modal (which I can't use, because it obscures navigation bar needed for my game) and custom.

I am an iOS programming newbie, but earlier I have developed an Adobe AIR mobile app and there it was possible to 1) replace view instead of pushing and 2) remove an unneeded view from navigation stack.

How to do the same in a native app please?

like image 431
Alexander Farber Avatar asked Jan 28 '14 19:01

Alexander Farber


People also ask

How do I remove a view controller from navigation stack?

Use this code and enjoy: NSMutableArray *navigationArray = [[NSMutableArray alloc] initWithArray: self. navigationController. viewControllers]; // [navigationArray removeAllObjects]; // This is just for remove all view controller from navigation stack.

How do I remove navigation controller from storyboard?

1) select navigation controller and delete connection. do same as shown in images and don't delete navigation controller at last step as i written in answer's last line. keep it disconnected as it is shown. Thanks that was it.

How do I segue to another view controller?

Well, in addition to that, Ctrl+dragging also helps set up segues. So, Ctrl+Drag from the “Go to Other View Controller” button, to somewhere in the second View Controller. It can be anywhere in the main box of the second view controller. When you release, it will show you a box like the one below.


2 Answers

To expand on the various segues above, this is my solution. It has the following advantages:

  • Can work anywhere in the view stack, not just the top view (not sure if this is realistically ever needed or even technically possible to trigger, but hey it's in there).
  • It doesn't cause a pop OR transition to the previous view controller before displaying the replacement, it just displays the new controller with a natural transition, with the back navigation being to the same back navigation of the source controller.

Segue Code:

- (void)perform {     // Grab Variables for readability     UIViewController *sourceViewController = (UIViewController*)[self sourceViewController];     UIViewController *destinationController = (UIViewController*)[self destinationViewController];     UINavigationController *navigationController = sourceViewController.navigationController;      // Get a changeable copy of the stack     NSMutableArray *controllerStack = [NSMutableArray arrayWithArray:navigationController.viewControllers];     // Replace the source controller with the destination controller, wherever the source may be     [controllerStack replaceObjectAtIndex:[controllerStack indexOfObject:sourceViewController] withObject:destinationController];      // Assign the updated stack with animation     [navigationController setViewControllers:controllerStack animated:YES]; } 
like image 195
ima747 Avatar answered Sep 21 '22 10:09

ima747


You could use a custom segue: to do it you need to create a class subclassing UIStoryboardSegue (example MyCustomSegue), and then you can override the "perform" with something like this

-(void)perform {     UIViewController *sourceViewController = (UIViewController*)[self sourceViewController];     UIViewController *destinationController = (UIViewController*)[self destinationViewController];     UINavigationController *navigationController = sourceViewController.navigationController;     // Pop to root view controller (not animated) before pushing     [navigationController popToRootViewControllerAnimated:NO];     [navigationController pushViewController:destinationController animated:YES];     } 

At this point go to Interface Builder, select "custom" segue, and put the name of your class (example MyCustomSegue)

In swift

override func perform() {     if let navigationController = self.source.navigationController {         navigationController.setViewControllers([self.destination], animated: true)     } } 
like image 35
Daniele Avatar answered Sep 18 '22 10:09

Daniele