[ios] Creating a segue programmatically

I have a common UIViewController that all my UIViewsControllers extend to reuse some common operations.

I want to set up a segue on this "Common" UIViewController so that all the other UIViewControllers inherit.

I am trying to figure out how do I do that programmatically.

I guess that the question could also be how do I set a segue for all my UIViewControllers without going into the story board and do them by hand.

This question is related to ios objective-c segue

The answer is


I reverse-engineered and made an open source (re)implementation of UIStoryboard's segues: https://github.com/acoomans/Segway

With that library, you can define segues programmatically (without any storyboard).

Hope it may help.


Here is the code sample for Creating a segue programmatically:

class ViewController: UIViewController {
    ...
    // 1. Define the Segue
    private var commonSegue: UIStoryboardSegue!
    ...
    override func viewDidLoad() {
        ...
        // 2. Initialize the Segue
        self.commonSegue = UIStoryboardSegue(identifier: "CommonSegue", source: ..., destination: ...) {
            self.commonSegue.source.showDetailViewController(self.commonSegue.destination, sender: self)
        }
        ...
    }
    ...
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // 4. Prepare to perform the Segue
        if self.commonSegue == segue {
            ...
        }
        ...
    }
    ...
    func actionFunction() {
        // 3. Perform the Segue
        self.prepare(for: self.commonSegue, sender: self)
        self.commonSegue.perform()
    }
    ...
}

First of, suppose you have two different views in storyboard, and you want to navigate from one screen to another, so follow this steps:

1). Define all your views with class file and also storyboard id in identity inspector.

2). Make sure you add a navigation controller to the first view. Select it in the Storyboard and then Editor >Embed In > Navigation Controller

3). In your first class, import the "secondClass.h"

#import "ViewController.h
#import "secondController.h"

4). Add this command in the IBAction that has to perform the segue

secondController *next=[self.storyboard instantiateViewControllerWithIdentifier:@"second"];
[self.navigationController pushViewController:next animated:YES];

5). @"second" is secondview controller class, storyboard id.


I've been using this code to instantiate my custom segue subclass and run it programmatically. It seems to work. Anything wrong with this? I'm puzzled, reading all the other answers saying it cannot be done.

UIViewController *toViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"OtherViewControllerId"];
MyCustomSegue *segue = [[MyCustomSegue alloc] initWithIdentifier:@"" source:self destination:toViewController];
[self prepareForSegue:segue sender:sender];
[segue perform];

I thought I would add another possibility. One of the things you can do is you can connect two scenes in a storyboard using a segue that is not attached to an action, and then programmatically trigger the segue inside your view controller. The way you do this, is that you have to drag from the file's owner icon at the bottom of the storyboard scene that is the segueing scene, and right drag to the destination scene. I'll throw in an image to help explain.

enter image description here

A popup will show for "Manual Segue". I picked Push as the type. Tap on the little square and make sure you're in the attributes inspector. Give it an identifier which you will use to refer to it in code.

enter image description here

Ok, next I'm going to segue using a programmatic bar button item. In viewDidLoad or somewhere else I'll create a button item on the navigation bar with this code:

UIBarButtonItem *buttonizeButton = [[UIBarButtonItem alloc] initWithTitle:@"Buttonize"
                                                                    style:UIBarButtonItemStyleDone
                                                                   target:self
                                                                   action:@selector(buttonizeButtonTap:)];
self.navigationItem.rightBarButtonItems = @[buttonizeButton];

Ok, notice that the selector is buttonizeButtonTap:. So write a void method for that button and within that method you will call the segue like this:

-(void)buttonizeButtonTap:(id)sender{
    [self performSegueWithIdentifier:@"Associate" sender:sender];
    }

The sender parameter is required to identify the button when prepareForSegue is called. prepareForSegue is the framework method where you will instantiate your scene and pass it whatever values it will need to do its work. Here's what my method looks like:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"Associate"])
    {
        TranslationQuizAssociateVC *translationQuizAssociateVC = [segue destinationViewController];
        translationQuizAssociateVC.nodeID = self.nodeID; //--pass nodeID from ViewNodeViewController
        translationQuizAssociateVC.contentID = self.contentID;
        translationQuizAssociateVC.index = self.index;
        translationQuizAssociateVC.content = self.content;
    }
}

Ok, just tested it and it works. Hope it helps you.


Storyboard Segues are not to be created outside of the storyboard. You will need to wire it up, despite the drawbacks.

UIStoryboardSegue Reference clearly states:

You do not create segue objects directly. Instead, the storyboard runtime creates them when it must perform a segue between two view controllers. You can still initiate a segue programmatically using the performSegueWithIdentifier:sender: method of UIViewController if you want. You might do so to initiate a segue from a source that was added programmatically and therefore not available in Interface Builder.

You can still programmatically tell the storyboard to present a view controller using a segue using presentModalViewController: or pushViewController:animated: calls, but you'll need a storyboard instance.

You can call UIStoryboards class method to get a named storyboard with bundle nil for the main bundle.

storyboardWithName:bundle:


You have to link your code to the UIStoryboard that you're using. Make sure you go into YourViewController in your UIStoryboard, click on the border around it, and then set its identifier field to a NSString that you call in your code.

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" 
                                                     bundle:nil];
YourViewController *yourViewController = 
 (YourViewController *)
  [storyboard instantiateViewControllerWithIdentifier:@"yourViewControllerID"];
[self.navigationController pushViewController:yourViewController animated:YES];

A couple of problems, actually:

First, in that project you uploaded for us, the segue does not bear the "segue1" identifier:

no identifier

You should fill in that identifier if you haven't already.

Second, as you're pushing from table view to table view, you're calling initWithNibName to create a view controller. You really want to use instantiateViewControllerWithIdentifier.


well , you can create and also can subclass the UIStoryBoardSegue . subclassing is mostly used for giving custom transition animation.

you can see video of wwdc 2011 introducing StoryBoard. its available in youtube also.

http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIStoryboardSegue_Class/Reference/Reference.html#//apple_ref/occ/cl/UIStoryboardSegue


For controllers that are in the storyboard.

jhilgert00 is this what you were looking for?

-(IBAction)nav_goHome:(id)sender {
UIViewController *myController = [self.storyboard instantiateViewControllerWithIdentifier:@"HomeController"];
[self.navigationController pushViewController: myController animated:YES];

}

OR...

[self performSegueWithIdentifier:@"loginMainSegue" sender:self];

Guess this is answered and accepted, but I just would like to add a few more details to it.

What I did to solve a problem where I would present a login-view as first screen and then wanted to segue to the application if login were correct. I created the segue from the login-view controller to the root view controller and gave it an identifier like "myidentifier".

Then after checking all login code if the login were correct I'd call

[self performSegueWithIdentifier: @"myidentifier" sender: self];

My biggest misunderstanding were that I tried to put the segue on a button and kind of interrupt the segue once it were found.


I'd like to add a clarification...

A common misunderstanding, in fact one that I had for some time, is that a storyboard segue is triggered by the prepareForSegue:sender: method. It is not. A storyboard segue will perform, regardless of whether you have implemented a prepareForSegue:sender: method for that (departing from) view controller.

I learnt this from Paul Hegarty's excellent iTunesU lectures. My apologies but unfortunately cannot remember which lecture.

If you connect a segue between two view controllers in a storyboard, but do not implement a prepareForSegue:sender: method, the segue will still segue to the target view controller. It will however segue to that view controller unprepared.

Hope this helps.


Examples related to ios

Adding a UISegmentedControl to UITableView Crop image to specified size and picture location Undefined Symbols error when integrating Apptentive iOS SDK via Cocoapods Keep placeholder text in UITextField on input in IOS Accessing AppDelegate from framework? Autoresize View When SubViews are Added Warp \ bend effect on a UIView? Speech input for visually impaired users without the need to tap the screen make UITableViewCell selectable only while editing Xcode 12, building for iOS Simulator, but linking in object file built for iOS, for architecture arm64

Examples related to objective-c

Adding a UISegmentedControl to UITableView Keep placeholder text in UITextField on input in IOS Accessing AppDelegate from framework? Warp \ bend effect on a UIView? Use NSInteger as array index Detect if the device is iPhone X Linker Command failed with exit code 1 (use -v to see invocation), Xcode 8, Swift 3 ITSAppUsesNonExemptEncryption export compliance while internal testing? How to enable back/left swipe gesture in UINavigationController after setting leftBarButtonItem? Change status bar text color to light in iOS 9 with Objective-C

Examples related to segue

Programmatically go back to previous ViewController in Swift IOS - How to segue programmatically using swift What's the difference between all the Selection Segues? How to perform Unwind segue programmatically? Creating a segue programmatically Perform Segue programmatically and pass parameters to the destination view