I have a small iPhone app, which uses a navigation controller to display 3 views (here fullscreen):
To expand on the various segues above, this is my solution. It has the following advantages:
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];
}
What you should really do is modally present a UINavigationController
containing the social network UIViewControllers
overtop of your Menu UIViewController
(which can be embedded in a UINavigationController
if you want). Then, once a user has authenticated, you dismiss the social network UINavigationController
, showing your Menu UIViewController
again.
In swift3
create one segue
-add identifier
-add and set in segue(storyboard) custom storyboard class from cocoatouch file
-In custom class override perform()
override func perform() {
let sourceViewController = self.source
let destinationController = self.destination
let navigationController = sourceViewController.navigationController
// Pop to root view controller (not animated) before pushing
if self.identifier == "your identifier"{
navigationController?.popViewController(animated: false)
navigationController?.pushViewController(destinationController, animated: true)
}
}
-You also have to override one method in your source viewcontroller
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
return false
}
Here a quick Swift 4/5 solution by creating a custom seque that replaces the (top stack) viewcontroller with the new one (without animation) :
class SegueNavigationReplaceTop: UIStoryboardSegue {
override func perform () {
guard let navigationController = source.navigationController else { return }
navigationController.popViewController(animated: false)
navigationController.pushViewController(destination, animated: false)
}
}
The custom segue didn't work for me, as I had a Splash view controller and I wanted to replace it. Since there was just one view controller in the list, the popToRootViewController
still left the Splash on the stack. I used the following code to replace the single controller
-(void)perform {
UIViewController *sourceViewController = (UIViewController*)[self sourceViewController];
UIViewController *destinationController = (UIViewController*)[self destinationViewController];
UINavigationController *navigationController = sourceViewController.navigationController;
[navigationController setViewControllers:@[destinationController] animated:YES];
}
and now in Swift 4:
class ReplaceSegue: UIStoryboardSegue {
override func perform() {
source.navigationController?.setViewControllers([destination], animated: true)
}
}
and now in Swift 2.0
class ReplaceSegue: UIStoryboardSegue {
override func perform() {
sourceViewController.navigationController?.setViewControllers([destinationViewController], animated: true)
}
}
Well, what you can also do is to use the unwind view controller stuff.
Actually I think that this is exactly what you need.
Check this entry: What are Unwind segues for and how do you use them?