Segue is executed twice - ios

I am trying to transition between view controllers with a segue. It is navigating correctly but it is running twice.
Here is my code:
- (IBAction)onActionNext:(id)sender {
if ([[nameField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]isEqualToString:#""]) {
}else if([[emailField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] isEqualToString:#""]){
}else if([[mobileField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] isEqualToString:#""]){
}else{
[self performSegueWithIdentifier:#"VerifyNext" sender:sender];
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:#"VerifyNext"]) {
// Get destination view
OTPSceneViewController *vc = [segue destinationViewController];
[vc setTitle:#"myapp"];
}
}

If even after commenting this line segue still run then as #mikealter said segue is connected your button. Check if when you check for when you click segue what it highlights.
A button like:
Or A View Controller like:
If you fall in first case that means your segue is connected to a button and, that is the reason why it opens next page even if you comment your code. And 2 times when you keep code(one from storyboard and another from code).
Edit:
If you want to call next page from code only. Remove Segue. Then reconnect it with view controller like:

First, whenever you create a segue (i.example) FROM a Button TO a View Controller, you are creating the link between VC1 and VC2.
If you run your project you will see that the segue works navigating from one VC to the other one.
This means that it already performs the segue, so if you declare an ACTION for your button and make a call to - perform segue... - it will run twice.
Note: if you call performSegueWithIdentifier is probably because you want to pass some data via SENDER. In that case you (obviously) need to call the segue ONCE, so instead of creating the segue from the button to the next VC, (first delete that segue), create a new one FROM the VCOrigin to VCDestination -> there are many ways to do it, but from the Interface Builder is as simple as right click on the top yellow rounded icon and drag&drop on the destinationVC. Don't forget to set the identifier on the Attributes Inspector.
Now, in your button~Action make the call to performSegueWithIdentifier and pass the data.

if you stop storyboard segue use following method:
override func shouldPerformSegueWithIdentifier(identifier: String,sender: AnyObject?) -> Bool {
return false
}

You don't even add
[self performSegueWithIdentifier:#"VerifyNext" sender:sender];
in onActionNext method if you add the segue in storyboard
If you want to navigate to next view controller use above line.
Preparing for the Segue
In order to pass information from one view controller to another using
the UIStoryboardSegue object we’ll need to take advantage of the
current view controller’s prepareForSegue:sender: method.
But If you call both,it calls two times.So make sure that whether you want to pass information or data to next view controller or just navigate the view.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog(#"prepareForSegue: %#", segue.identifier);
if([segue.identifier isEqualToString:#"VerifyNext"])
{
VerifyNextViewController *verifyNVC = segue.destinationViewController;
verifyNVC.name = #"Prashabt";
verifyNVC.id = #"1234";
}
else if([segue.identifier isEqualToString:#"VerSeg"])
{
AnotherViewController *anotherVC = segue.destinationViewController;
anotherVC.name = #"Sharma";
anotherVC.id = #"3245";
}
}

have a look of this question this may sure rectify
or there is another way to navigate to another view controller using below code.
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier:#"viewControllerName"];
[self.navigationController pushViewController:vc animated:YES];
make sure you give identity to the view controller using identity inspector see image.

Related

Programmatically segue..works ever

I'm trying to create a manual segue, which happens only if there is a certain conidition (a successful login).
The steps I have followed are these:
1) I've created a button in source viewcontroller, and i connected the button with a drag with the destination viewcontroller.
2) I set the identifier for the segue, calling it login_ok
3) I've created a -(IBAction)buttonPressed:(id)sender
Now, I tried to make an example, to see if the work or not. I wrote:
- (IBAction)buttonPressed:(id)sender
{
BOOL test = false;
if(test == true)
{
[self performSegueWithIdentifier:#"login_ok" sender:self];
}
Theoretically, the segue should not work, because i set test=false, and i said the segue should work only if test=true.
But the segue works and makes me go to the destination viewcontroller.
Why?
If you connected the button with a drag to the destination controller, it should segue anyway.
You need to connect the segue between screens and not from the button to the screen. Then, you can control your segue from the code.
You should define your segue between controllers not from button to the controller. Defining segue between view controllers is more useful than defining segue from any component to a view controller, because when you want to use a condition for any action, you can use these two methods effectively
[self performSegueWithIdentifier:#"segueID" sender:self];
and
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
For example:
- (IBAction)buttonPressed:(id)sender
{
BOOL test = YES;
if(test == YES)
[self performSegueWithIdentifier:#"login_ok" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"login_ok"])
{
YourNextController *controller = [segue destinationViewController];
controller.welcomeText = #"Hi! Test is true congratulations";
}
}
Especially passing data from controller to another one, this way is always useful.

Need some insight to make a 3 UIButton menu in XCode that toggles and changes dataset in the main ViewController

I'm new on Stackoverflow and I'm currently learning XCode from scratch and I'm in a process of making a Single Page Application with options.
Anyone knows how to efficiently make a simple menu with multiple selectable UIButtons that make the main ViewController display different datasets depending on the selection in XCode?
Tried different things (creating SecondViewController for example but can't figure out how to pass data from it to main ViewController).
Any help will be greatly appreciated.
Refer this:
https://www.appcoda.com/storyboards-ios-tutorial-pass-data-between-view-controller-with-segue/
How to pass prepareForSegue: an object
Simple Test from above Answer Reference:
Simply grab a reference to the target view controller in prepareForSegue: method and pass any objects you need to there. Here's an example...
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"YOUR_SEGUE_NAME_HERE"])
{
// Get reference to the destination view controller
YourViewController *vc = [segue destinationViewController];
// Pass any objects to the view controller here, like...
[vc setMyObjectHere:object];
}
}
REVISION: You can also use performSegueWithIdentifier:sender: method to activate the transition to a new view based on a selection or button press.
For instance, consider I had two view controllers. The first contains three buttons and the second needs to know which of those buttons has been pressed before the transition. You could wire the buttons up to an IBAction in your code which uses performSegueWithIdentifier: method, like this...
//When any of my buttons are pressed, push the next view
- (IBAction)buttonPressed:(id)sender
{
[self performSegueWithIdentifier:#"MySegue" sender:sender];
}
// This will get called too before the view appears
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"MySegue"]) {
// Get destination view
SecondView *vc = [segue destinationViewController];
// Get button tag number (or do whatever you need to do here, based on your object
NSInteger tagIndex = [(UIButton *)sender tag];
// Pass the information to your destination view
[vc setSelectedButton:tagIndex];
}
}
Hope this help but please go through refernces!

Using pushViewController is very slow on iPad

I'm trying to move from one UIViewController to another using -pushViewController:animated using the below snipped :
SomeController *tabBar = [self.storyboard instantiateViewControllerWithIdentifier:#"mycus"];
[self.navigationController pushViewController:tabBar animated:YES];
Moving from one UIViewController (which has no UIViews or images) has a 3 second delay before moving. What is causing this issue and how would I solve it?
For storyboard, click on the segue you have created, give it an identifier like "someSegue".
Next you will want to trigger the prepareForSegue delegate in your viewcontroller doing the following...
[self performSegueWithIdentifier:#"SomeSegue" sender:nil];
..Then you will want to include the delegate method in your view controller and do any preparing you might want before the next view controller is initialised.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
SomeController *vc = [segue destinationViewController];
// Here you will want to do your prep e.g. pass iVars etc from one controller to the other.
}

Perform Segue With Identifier for already Instiated View Controller

I'm trying to use a custom segue (at bottom) to present a view controller modally with a blur view. I need to instantiate the view controller with properties before I present the view controller.
Instating the VC works great when I am using pushVC, but when I use perform segue with identifier, I don't see an option to choose an already instantiated VC.
CustomViewController* VC = [self.navigationController.storyboard instantiateViewControllerWithIdentifier:#"customVC"];
[self.navigationController performSegueWithIdentifier:#"blurSegue" sender:self];
How can I perform the custom segue and force it to use the view controller I allocated (called VC above)?
https://github.com/AlvaroFranco/AFBlurSegue
I need to instantiate the view controller with properties before I
present the view controller.
Why do you have to instantiate CustomViewController before triggering the segue. That shouldn't be necessary, if you need access to a property of CustomViewController before it's shown, you can set it in prepareForSegue.
Try this:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"blurSegue"]) {
CustomViewController *customViewController = (CustomViewController *)segue.destinationViewController;
customViewController.propertyToSet = XXX; // set the property here
}
}
Ah, by the way, instead of
[self.navigationController performSegueWithIdentifier:#"blurSegue" sender:self];
just use:
[self performSegueWithIdentifier:#"blurSegue" sender:self];

implement 2 cancel button in a segue

I have a view controller with 2 different segues that goes to 2 different view controller,and i have to implement the cancel button in both the controllers.When i press the cancel button,in both the controller,the view will return to the initial view controller.My question is how can i implement the buttons?When i try with this code the compiler warning:Multiple declaration of method "cancel:" found and ignored.Thank you.
interface:
-(IBAction)cancel:(UIStoryboardSegue *)segue;
-(IBAction)done:(UIStoryboardSegue *)segue;
-(IBAction)cancel:(UIStoryboardSegue *)segue;
implementation:
-(IBAction)done:(UIStoryboardSegue *)segue
{
if([[segue identifier] isEqualToString:#"ReturnInput"]){
AddSightingViewController *addController = [segue sourceViewController];
if (addController.birdSighting) {
[self.dataController
addBirdSightingWithSighting:addController.birdSighting];
[[self tableView]reloadData];
}
[self dismissViewControllerAnimated:YES completion:NULL];
}
}
-(IBAction)cancel:(UIStoryboardSegue *)segue
{
if([[segue identifier] isEqualToString:#"CancelInput"]){
[self dismissViewControllerAnimated:YES completion:NULL];
}
}
I'm not sure of what you're trying to do. But I think the cancel method needs to be in the 2 child View Controllers, not in the main one. One for each controller (and one cancel button for each view). That way you won't have any problems with multiple declarations of a method.
From your code I conclude that you are using (or want use) exit segues for canceling.
First, you should only have one method declaration and implementation for your cancel method in the initial view controller. In your storyboard create exit segues by control-dragging from your cancel buttons to the green exit icon blow the view controller and select the cancel method defined in the initial view controller. Do that for both view controllers. You should also give your exit segues different identifiers in your storyboard (you need to select the segue in the Document Outline to change its identifier).
Then your cancel method in your initial view controller can look something like this:
-(IBAction)cancel:(UIStoryboardSegue *)segue
{
if([[segue identifier] isEqualToString:#"CancelInput1"]) {
// Do something
} else if([[segue identifier] isEqualToString:#"CancelInput2"]) {
// Do something different
}
}
If you don't want to do anything when canceling just leave the method empty.
If you wan't to go back you need to implement an unwind segue.
To do this, define a method to go back on the original view controller (the one you want to go back). You can leave the method empty.
- (IBAction)methodName:(UIStoryboardSegue *)segue
{
}
Then on IB ctrl + drag from the button (or from the view controller) to the green "exit" icon. Select the methodName from the popup menu. If you did it from the view controller set the identifier on the segue and call it with performSegueWithIdentifier: from the button action.
Considerations:
The method name will be detected in every view controller on the storyboard.
You can define the same method name in different view controllers, but when you execute the unwind segue, you will go back to the most recent on the navigation path.

Resources