5

This may be very rookie but...

I've set a segue between two ViewControllers in my Storyboard, with the identifier clickBtn.

Now I'm calling it this way in my code:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"clickBtn"])
    {
        if(conditionVerified)
        {
            SecondViewController *controller = (SecondViewController *)segue.destinationViewController;
            [controller setManagedObjectContext:self.managedObjectContext];
        }
        else
        {
            // If I enter here I get the error below
        }
    }
}

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+entityForName: nil is not a legal NSManagedObjectContext parameter searching for entity name 'Link''

In fact I don't want to do this transition if I enter the else-statement. How to do so?

Rob
  • 15,732
  • 22
  • 69
  • 107
  • Which textField? Or better where is the text field? – alecnash Nov 05 '13 at 21:46
  • I think error in code where you are trying to create managed object. Is it in SecondViewController init method? Please, show us this code. – opedge Nov 05 '13 at 21:50
  • [self managedObjectContext] is nil I suppose. Where do you set that? – alecnash Nov 05 '13 at 21:50
  • @opedge That's it but in fact, I'm facing this problem because I don't want to do this segue if I enter the else-statement. – Rob Nov 05 '13 at 21:52
  • @alecnash Yes my managedObjectContext is nil because I'm pushing the view in any case, but what I don't know to do is how to avoid doing this segue if conditionVerified is false. – Rob Nov 05 '13 at 21:54
  • 1
    @Rob I think you should set segue identifier in Storyboard and then manually perform this segue after your check: [self performSegueWithIdentifier: sender:nil]; – opedge Nov 05 '13 at 21:56
  • possible duplicate of [Prevent segue in prepareForSegue method?](http://stackoverflow.com/questions/8066525/prevent-segue-in-prepareforsegue-method) – Pang Oct 22 '14 at 07:19

5 Answers5

16

To optionally suppress a transition, implement

- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender

and return YES or NO, depending on your condition. In your example:

- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
    if ([identifier isEqualToString:@"clickBtn"])  {
        return conditionVerified;
    } else {
        return YES;
    }
}

In prepareForSegue: it is "too late" to suppress the transition.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • Nice answer. But please note that `segue` is not there in the context of method. Just use [identifier isEqualToString:@"clickBtn"]. – haxpor Feb 16 '15 at 04:37
7

Rather than having the button perform the segue have it call a method like the following.

-(IBAction)mySegueButtonMethod:(id)sender
{
   if(conditionVerified){
      [self performSegueWithIdentifier:@"clickBtn" sender:sender];
   }
   else{
        // do not perform segue and do other relevant actions.
   }
}

The error you are seeing is because i am assuming controller is calling something that needs context manager not to be nil.

You can't really stop the segue from occurring once you are in the method prepareForSegue as it will always perform the segue at the end of the method.

Ben Avery
  • 1,724
  • 1
  • 20
  • 33
  • Not really the best answer. Part of the reason for using segues is that there is no need to hook up action methods for simple things such as button taps or table view cell selections. The other answers that use `shouldPerformSegueWithIdentifier:sender:` are much more in keeping with this. – Abizern Nov 06 '13 at 10:10
4

You should refactor your code differently for this purpose. Implement shouldPerformSegueWithIdentifier like below:

-(BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender {
    return [identifier isEqualToString:@"clickBtn"] && conditionVerified;
}

It would prevent the segue "clickBtn" to be executed if the condition is not verified, i.e. conditionVerified is false. Now use:

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([[segue identifier] isEqualToString:@"clickBtn"] && conditionVerified) { //just a double checking
        SecondViewController *controller = (SecondViewController *)segue.destinationViewController;
        [controller setManagedObjectContext:self.managedObjectContext];
    }
}

And this would prepare your segue for execution, only if shouldPerformSegueWithIdentifier return YES(true). So you would never have to face any unintended transition if condition is not verified.

Hope it helps.

jhilgert00
  • 5,479
  • 2
  • 38
  • 54
Ayan Sengupta
  • 5,238
  • 2
  • 28
  • 40
2

Try This .It worked for me!

- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
{
    if ([identifier isEqualToString:@"Login"] && condition )
        { 
            return YES;
        }
        else if ([identifier isEqualToString:@"SignUp"])
        {
            return YES;
        }
        else
        {
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"OOPS!!" message:@"Incorrect Username Or Password" delegate:self cancelButtonTitle:nil otherButtonTitles:@"OK",nil];

            return NO;
        }

    }
     return YES;
}
0

A better way is to use the method shouldPerformSegueWithIdentifier as mentioned here: https://stackoverflow.com/a/12818366/2500457

Community
  • 1
  • 1
iphondroid
  • 498
  • 7
  • 19