How to perform Unwind segue programmatically? - ios

Using storyboard this is very easy. You just drag the action to "Exit". But how should I call it from my code?

Create a manual segue (ctrl-drag from File’s Owner to Exit),
Choose it in the Left Controller Menu below green EXIT button.
Insert Name of Segue to unwind.
Then,- (void)performSegueWithIdentifier:(NSString *)identifier sender:(id)sender. with your segue identify.

Here's a complete answer with Objective C and Swift:
1) Create an IBAction unwind segue in your destination view controller (where you want to segue to). Anywhere in the implementation file.
// Objective C
- (IBAction)unwindToContainerVC:(UIStoryboardSegue *)segue {
}
// Swift
#IBAction func unwindToContainerVC(segue: UIStoryboardSegue) {
}
2) On the source view controller (the controller you're segueing from), ⌃ + drag from "Name of activity" to exit. You should see the unwind segue created in step 1 in the popup. (If you don't see it, review step one). Pick unwindToContainerVC: from the popup, or whatever you named your method to connect your source controller to the unwind IBAction.
3) Select the segue in the source view controller's document outline of the storyboard (it will be listed near the bottom), and give it an identifier.
4) Call the unwind segue using this method from source view controller, substituting your unwind segue name.
// Objective C
[self performSegueWithIdentifier:#"unwindToContainerVC" sender:self];
// Swift
self.performSegueWithIdentifier("unwindToContainerVC", sender: self)
NB. Use the sourceViewController property of the segue parameter on the unwind method to access any exposed properties on the source controller. Also, notice that the framework handles dismissing the source controller. If you'd like to confirm this add a dealloc method to the source controller with a log message that should fire once it has been killed. If dealloc doesn't fire you may have a retain cycle.

bradleygriffith's answer was great. I took step 10 and made a screenshot for simplification. This is a screenshot in Xcode 6.
Control-drag from the orange icon to the red Exit icon to create an unwind without any actions/buttons in the view.
Then select the unwind segue in the sidebar:
Set a Segue Identifier string:
Access that identifier from code:
[self performSegueWithIdentifier:#"unwindIdentifier" sender:self];

I used [self dismissViewControllerAnimated: YES completion: nil]; which will return you to the calling ViewController.

Quoting text from Apple's Technical Note on Unwind Segue:
To add an unwind segue that will only be triggered programmatically, control+drag from the scene's view controller icon to its exit icon, then select an unwind action for the new segue from the popup menu.
Link to Technical Note

Vishal Chaudhry's answer above worked for me. I would also add that in order to manually trigger the seque using:
[self performSegueWithIdentifier:#"mySegueName" sender:self];
from within the ViewController you must also select the unwind segue under the ViewController's Scene in the storyboard and in the properties view on the RHS ensure that the Indentifier field contains the namer you're referring to in the code ("mySegueName" in the example above).
If you omit this step, the line above will throw an exception that the seque name is not known.

SWIFT 4:
1. Create an #IBAction with segue inside controller you want to unwind to:
#IBAction func unwindToVC(segue: UIStoryboardSegue) {
}
2. In the storyboard, from the controller you want to segue (unwind) from ctrl+drag from the controller sign to exit sign and choose method you created earlier:
3. Now you can notice that in document outline you have new line with title "Unwind segue....". Now you should click on this line and open attribute inspector to set identifier (in my case unwindSegueIdentifier).
4. You're almost done! Now you need to open view controller you wish to unwind from and create some method that will perform segue. For example you can add button, connect it with code with #IBAction, after that inside this IBAction add perfromSegue(withIdentifier:sender:) method:
#IBAction func unwindToSomeVCWithSegue(_ sender: UIButton) {
performSegue(withIdentifier: "unwindSegueIdentifier", sender: nil)
}
So that is all you have to do!

Swift 4.2, Xcode 10+
For those wondering how to do this with VCs not set up via the storyboard (those coming to this question from searching "programmatically" + "unwind segue").
Given that you cannot set up an unwind segue programatically, the simplest solely programmatic solution is to call:
navigationController?.popToRootViewController(animated: true)
which will pop all view controllers on the stack back to your root view controller.
To pop just the topmost view controller from the navigation stack, use:
navigationController?.popViewController(animated: true)

Backwards compatible solution that will work for versions prior to ios6, for those interested:
- (void)unwindToViewControllerOfClass:(Class)vcClass animated:(BOOL)animated {
for (int i=self.navigationController.viewControllers.count - 1; i >= 0; i--) {
UIViewController *vc = [self.navigationController.viewControllers objectAtIndex:i];
if ([vc isKindOfClass:vcClass]) {
[self.navigationController popToViewController:vc animated:animated];
return;
}
}
}

FYI: In order for #Vadim's answer to work with a manual unwind seque action called from within a View Controller you must place the command:
[self performSegueWithIdentifier:(NSString*) identifier sender:(id) sender];
inside of the overriden class method viewDidAppear like so:
-(void) viewDidAppear:(BOOL) animated
{
[super viewDidAppear: animated];
[self performSegueWithIdentifier:#"SomeSegueIdentifier" sender:self];
}
If you put it in other ViewController methods like viewDidLoad or viewWillAppear it will be ignored.

Related

Recreate dismiss animation in Swift [duplicate]

Using storyboard this is very easy. You just drag the action to "Exit". But how should I call it from my code?
Create a manual segue (ctrl-drag from File’s Owner to Exit),
Choose it in the Left Controller Menu below green EXIT button.
Insert Name of Segue to unwind.
Then,- (void)performSegueWithIdentifier:(NSString *)identifier sender:(id)sender. with your segue identify.
Here's a complete answer with Objective C and Swift:
1) Create an IBAction unwind segue in your destination view controller (where you want to segue to). Anywhere in the implementation file.
// Objective C
- (IBAction)unwindToContainerVC:(UIStoryboardSegue *)segue {
}
// Swift
#IBAction func unwindToContainerVC(segue: UIStoryboardSegue) {
}
2) On the source view controller (the controller you're segueing from), ⌃ + drag from "Name of activity" to exit. You should see the unwind segue created in step 1 in the popup. (If you don't see it, review step one). Pick unwindToContainerVC: from the popup, or whatever you named your method to connect your source controller to the unwind IBAction.
3) Select the segue in the source view controller's document outline of the storyboard (it will be listed near the bottom), and give it an identifier.
4) Call the unwind segue using this method from source view controller, substituting your unwind segue name.
// Objective C
[self performSegueWithIdentifier:#"unwindToContainerVC" sender:self];
// Swift
self.performSegueWithIdentifier("unwindToContainerVC", sender: self)
NB. Use the sourceViewController property of the segue parameter on the unwind method to access any exposed properties on the source controller. Also, notice that the framework handles dismissing the source controller. If you'd like to confirm this add a dealloc method to the source controller with a log message that should fire once it has been killed. If dealloc doesn't fire you may have a retain cycle.
bradleygriffith's answer was great. I took step 10 and made a screenshot for simplification. This is a screenshot in Xcode 6.
Control-drag from the orange icon to the red Exit icon to create an unwind without any actions/buttons in the view.
Then select the unwind segue in the sidebar:
Set a Segue Identifier string:
Access that identifier from code:
[self performSegueWithIdentifier:#"unwindIdentifier" sender:self];
I used [self dismissViewControllerAnimated: YES completion: nil]; which will return you to the calling ViewController.
Quoting text from Apple's Technical Note on Unwind Segue:
To add an unwind segue that will only be triggered programmatically, control+drag from the scene's view controller icon to its exit icon, then select an unwind action for the new segue from the popup menu.
Link to Technical Note
Vishal Chaudhry's answer above worked for me. I would also add that in order to manually trigger the seque using:
[self performSegueWithIdentifier:#"mySegueName" sender:self];
from within the ViewController you must also select the unwind segue under the ViewController's Scene in the storyboard and in the properties view on the RHS ensure that the Indentifier field contains the namer you're referring to in the code ("mySegueName" in the example above).
If you omit this step, the line above will throw an exception that the seque name is not known.
SWIFT 4:
1. Create an #IBAction with segue inside controller you want to unwind to:
#IBAction func unwindToVC(segue: UIStoryboardSegue) {
}
2. In the storyboard, from the controller you want to segue (unwind) from ctrl+drag from the controller sign to exit sign and choose method you created earlier:
3. Now you can notice that in document outline you have new line with title "Unwind segue....". Now you should click on this line and open attribute inspector to set identifier (in my case unwindSegueIdentifier).
4. You're almost done! Now you need to open view controller you wish to unwind from and create some method that will perform segue. For example you can add button, connect it with code with #IBAction, after that inside this IBAction add perfromSegue(withIdentifier:sender:) method:
#IBAction func unwindToSomeVCWithSegue(_ sender: UIButton) {
performSegue(withIdentifier: "unwindSegueIdentifier", sender: nil)
}
So that is all you have to do!
Swift 4.2, Xcode 10+
For those wondering how to do this with VCs not set up via the storyboard (those coming to this question from searching "programmatically" + "unwind segue").
Given that you cannot set up an unwind segue programatically, the simplest solely programmatic solution is to call:
navigationController?.popToRootViewController(animated: true)
which will pop all view controllers on the stack back to your root view controller.
To pop just the topmost view controller from the navigation stack, use:
navigationController?.popViewController(animated: true)
Backwards compatible solution that will work for versions prior to ios6, for those interested:
- (void)unwindToViewControllerOfClass:(Class)vcClass animated:(BOOL)animated {
for (int i=self.navigationController.viewControllers.count - 1; i >= 0; i--) {
UIViewController *vc = [self.navigationController.viewControllers objectAtIndex:i];
if ([vc isKindOfClass:vcClass]) {
[self.navigationController popToViewController:vc animated:animated];
return;
}
}
}
FYI: In order for #Vadim's answer to work with a manual unwind seque action called from within a View Controller you must place the command:
[self performSegueWithIdentifier:(NSString*) identifier sender:(id) sender];
inside of the overriden class method viewDidAppear like so:
-(void) viewDidAppear:(BOOL) animated
{
[super viewDidAppear: animated];
[self performSegueWithIdentifier:#"SomeSegueIdentifier" sender:self];
}
If you put it in other ViewController methods like viewDidLoad or viewWillAppear it will be ignored.

How to do something before unwind segue action?

I've just figured out what is an unwind segue and how to use it with the great answers from this question. Thanks a lot.
However, here's a question like this:
Let's say there is a button in scene B which unwind segues to scene A, and before it segues I want something to be done, such as saving the data to database. I created an action for this button in B.swift, but it seems it goes directly to scene A without taking the action appointed.
Anyone knows why or how to do this?
Thank you.
You can do it the way you describe, or by using a prepareForSegue override function in the viewController you are unwinding from:
#IBAction func actionForUnwindButton(sender: AnyObject) {
println("actionForUnwindButton");
}
or...
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
println("prepareForSegue");
}
The first example is as you describe. The button is wired up to the unwind segue and to the button action in Interface Builder. The button action will be triggered before the segue action. Perhaps you didn't connect the action to the button in interface builder?
The second example gives you have access to the segue's sourceViewController and destinationViewController in case that is also useful (you also get these in the unwind segue's function in the destination view controller).
If you want to delay the unwind segue until the button's local action is complete, you can invoke the segue directly from the button action (instead of hooking it up in the storyboard) using self.performSegueWithIdentifier (or follow wrUS61's suggestion)
EDIT
you seem to have some doubts whether you can work this by wiring up your button both to an unwind segue and to a button action. I have set up a little test project like this:
class BlueViewController: UIViewController {
#IBAction func actionForUnwindButton(sender: AnyObject) {
println("actionForUnwindButton");
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
println("prepareForSegue");
}
}
class RedViewController: UIViewController {
#IBAction func unwindToRed(sender: UIStoryboardSegue) {
println("unwindToRed");
}
}
BlueViewController has a button that is connected in the storyboard to BOTH the unwindToRed unwind segue AND the actionForUnwindButton button. It also overrides prepareForSegue so we can log the order of play.
Output:
actionForUnwindButton
prepareForSegue
unwindToRed
Storyboard:
EDIT 2
your demo project shows this not working. The difference is that you are using a barButtonItem to trigger the action, whereas I am using a regular button. A barButtonItem fails, whereas a regular button succeeds. I suspect that this is due to differences in the order of message passing (what follows is conjecture, but fits with the observed behaviour):
(A) UIButton in View Controller
ViewController's button receives touchupInside
- (1) sends action to it's method
- (2) sends segue unwind action to storyboard segue
all messages received, and methods executed in this order:
actionForUnwindButton
prepareForSegue
unwindToRed
(B) UIBarButtonItem in Navigation Controller Toolbar
Tool bar buttonItem receives touchupInside
- (1) sends segue unwind action to storyboard segue
- (2) (possibly, then) sends action to viewController's method
Order of execution is
prepareForSegue
unwindToRed
actionForUnwindButton
prepareForSegue and unwind messages received. However actionForUnwindButton message is sent to nil as viewController is destroyed during the segue. So it doesn't get executed, and the log prints
prepareForSegue
unwindToRed
In the case of (B), the viewController is destroyed before the method reaches it, so does not get triggered
So it seems your options are...
(a) use a UIButton with action and unwind segue
(b) trigger your actions using prepareForSegue, which will be triggered while the viewController is still alive, and before the segue takes place.
(c) don't use an unwind segue, just use a button action. In the action method you can 'unwind' by calling popToViewController on your navigation controller.
By the way, if you implement a toolBar on the viewController (not using the navigation controller's toolbar) the result is the same: segue gets triggered first, so button action fails.
If you are able to perform unWind Segue Successfully. Then the method in destination View Controller is called just before the segue take place, you can do what ever you want in source viewcontroller by using the segue object.
- (IBAction)unwindToThisViewController:(UIStoryboardSegue *)unwindSegue
{
CustomViewController *vc = (CustomViewController*) unwindSegue.sourceViewController;
[vc performAnyMethod];
[vc saveData];
NSString *temp = vc.anyProperty;
}
if you want your logic in source Controller then implement prepareForSegue in Scene B and set the unWind segue Identifier from Storyboard > Left View hierarchy Panel > under Exit in Scene B.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier] isEqualToString:#"backToSource"])
{
NSLog(#"Going Back");
}
}
At first, you should call the send data function in prepareForSegue method.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([[segue identifier] isEqualToString:#"UnwindIdentifier"]) {
// send data
}
}
If you don't want to let unwind segue happen before getting response from the server, you should override
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
method and return NO;. Then you can perform segue manually when you get the server response by calling:
[self performSegueWithIdentifier:#"UnwindIdentifier" sender:sender];

Conditional Segue Using Storyboard

I just need to know how to make some 'conditional' redirect / segue to some view. For example :
If user haven't login yet, then a view with login form appears. But if user logged in already, they will see their profile view.
How to make conditional segue like that using storyboard?
Thank you
For conditional segues, don't start a segue from a button as you normally do.
Instead of that use the following steps:
In your storyboad, start a segue directly from the source view controller to the destination view controller. For doing this, you can drag your source view controller's icon on the bar just below the view to the destination view controller on the main canvas area. Just remember you have to connect two view controllers directly and not with any control.
Enter a suitable segue identifier for this segue. For example say "conditionSegue"
Now, in your source view controller’s .m file perform your condition and call -performSegueWithIdentifier:sender: method on "self" like this:
-(void)loadDestinationVC{
if(condition == YES){
[self performSegueWithIdentifier:#"conditionSegue" sender:nil];
}
}
I hope I made it clear.
I believe a better approach if you want to use segues from buttons would be to use this:
First create a button and use a segue to connect it to another view, give this segue a name
then use this method in your .m file
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender {
if ([identifier isEqualToString:#"SegueName"]) {
//Check if should make the segue
//if not do something
[self doSomething];
//and return NO;
return NO;
}
return YES;
}
In Swift you could do :
as #Gaurav Singh suggested in his answer
Step 1: Insert a segue from ViewControllerA to ViewControllerB. The segue should start from ViewControllerA itself and not from any control ( like Button ) in it.
Step 2: Give segue an unique identifier in storyboard. Ex: seageFromAtoB
Step 3 : In your ViewControllerforA.swift write :
if(condition == true) {
self.performSegueWithIdentifier("seageFromAtoB", sender: self)
}
If you are performing some task in some other Thread then using performSegueWithIdentifier can throw an exception.
If you get this error then you should use :
if(condition==true){
NSOperationQueue.mainQueue().addOperationWithBlock {
self.performSegueWithIdentifier("seageFromAtoB", sender: self)
}
}
This will perform segue redirection in main Thread.
Hope this help for someone looking for Swift option
You make the segues directly from one controller to another (or others), and give them identifiers. In code you call choose between segues depending on your conditions, and call performSegueWithIdentifier:sender:.
Create "generic" segue by ctrl dragging from the view controller icon at the bottom to the destination. This segue won't be associated with any action. Then, in your code where ever the event is using your conditional code that you want to trigger the segue, call:
- (void)performSegueWithIdentifier:(NSString *)identifier sender:(id)sender

Give IBAction priority instead of segue

I'm using storyboard, and in my storyboard I got a button which I connected with another view controller. So when you click the button, the other view controller shows up. I connected this using an Action Segue - Push in the storyboard. I also connected the button with an IBAction property. The problem is when I click the button it first goes to the view controller that its connected to, and after that it executes the IBAction function. How can I change this order?
You cannot change that order. There are two things that you can do.
First:
Use the segue only.
Overwrite prepareForSegue: and place your code there. If there is more than one segure from that view controller then you can distinguish within prepareForSegue: which one is currently being performed. For that you should provide them with unique names/segue IDs.
Second:
Use the IBAction only.
Within the IBAction method, at its very end, call performSegueWithIdentifier:sender:. Again, for that you will have to name all your segues with unique segue IDs.
The question to ask yourself is, why are you using both? Pick one and stick with it IMO.
If you want to perform some actions when the segue happens you should implement
prepareForSegue:
Update to address comment
I actually don't know how I can do it in code, how can I load a ViewController that is on my storyboard without using the Action Segue Push?
The easiest way that I've found is in your Storyboard you can set an identifier for the view controller.
Notice Storyboard ID is set to MyViewController
Now in your IBAction method you can do the following.
UIViewController *myViewController = [[UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil] instantiateViewControllerWithIdentifier:#"MyViewController"];
[self presentViewController:myViewController animated:YES completion:nil];
I solved this by chaining the IBAction from my segue. I find this approach the most useful as I can have a "save" action without a segue (chain a button to the IBAction, sometimes useful), and also use a segue for dismissing the view controller when necessary.
-(IBAction)save:(id)sender
{
/* Do some Save stuff */
}
Then in my prepareForSegue:sender:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"save"])
{
[self save:sender];
}
}
Link up your non-segue buttons to the IBAction, and segue your unwind or other such buttons with an identifier as "save". Magic.

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.
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.
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.
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;
}
}
I tested it and it works.
By definition a segue can't really exist independently of a storyboard. It's even there in the name of the class: UIStoryboardSegue. You don't create segues programmatically - it is the storyboard runtime that creates them for you. You can normally call performSegueWithIdentifier: in your view controller's code, but this relies on having a segue already set up in the storyboard to reference.
What I think you are asking though is how you can create a method in your common view controller (base class) that will transition to a new view controller, and will be inherited by all derived classes. You could do this by creating a method like this one to your base class view controller:
- (IBAction)pushMyNewViewController
{
MyNewViewController *myNewVC = [[MyNewViewController alloc] init];
// do any setup you need for myNewVC
[self presentModalViewController:myNewVC animated:YES];
}
and then in your derived class, call that method when the appropriate button is clicked or table row is selected or whatever.
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];
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.
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];
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];
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
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.
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:
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 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.
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.
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()
}
...
}

Resources