I use the method performSegueWithIdentifier:sender:
to open a new ViewController
from a storyboard-file programmatically. This works like a charm.<
To reuse an existing UIViewController
instance with a segue create the segue from scratch and provide your own (existing) destination (UIViewController
). Do not forget to call prepareForSegue:
if needed.
For example:
UIStoryboardSegue* aSegue = [[UIStoryboardSegue alloc] initWithIdentifier:@"yourSegueIdentifier" source:self destination:self.existingViewController]
[self prepareForSegue:aSegue sender:self];
[aSegue perform];
Following code makes singleton view controller. Add them to your destination view controller implementation, then segue will reuse the same vc.
static id s_singleton = nil;
+ (id) alloc {
if(s_singleton != nil)
return s_singleton;
return [super alloc];
}
- (id) initWithCoder:(NSCoder *)aDecoder {
if(s_singleton != nil)
return s_singleton;
self = [super initWithCoder:aDecoder];
if(self) {
s_singleton = self;
}
return self;
}
Firstly you would be going against Apple's design in Using Segues: "A segue always presents a new view controller".
To understand why it might help to know that what a segue does is create a new view controller and then the perform calls either showViewController or showDetailViewController depending on what kind of segue it is. So if you have an existing view controller just call those methods! e.g.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
Event *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
self.detailViewController.detailItem = object;
[self showDetailViewController:self.detailViewController.navigationController sender:self];
}
I faced this problem today and what I have done is to create the view controller manually and store it's reference. Then every time I need the controller, check first if exists. Something like this:
MyController *controller = [storedControllers valueForKey:@"controllerName"];
if (!controller)
{
controller = [[UIStoryboard storyboardWithName:@"MainStoryboard_iPhone" bundle:NULL] instantiateViewControllerWithIdentifier:@"MyControllerIdentifierOnTheStoryboard"];
[storedControllers setValue:controller forKey:@"controllerName"];
}
[self.navigationController pushViewController:controller animated:YES];
Hope it helps.
You would need to make the Viewcontroller into a singleton class.
Use shouldPerforSegueWithIdentifier to either allow the segue to perform or to cancel the segue and manually add your ViewController. Retain a pointer in the prepareForSegue.
... header
@property (strong, nonatomic) MyViewController *myVC;
... implementation
-(BOOL) shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender{
if([identifier isEqualToString:@"MySegueIdentifier"]){
if(self.myVC){
// push on the viewController
[self.navigationController pushViewController:self.myVC animated:YES];
// cancel segue
return NO;
}
}
// allow the segue to perform
return YES;
}
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:@"MySegueIdentifier"]){
// this will only be called the first time the segue fires for this identifier
// retian a pointer to the view controller
self.myVC = segue.destinationViewController;
}
}