39

Using iOS 5 storyboards, on a button I am performing a segue, what I want is to do validation on my textfield and if validation is failed I have to stop segue and throw an alert. Whats the way to do it?

Firdous
  • 4,624
  • 13
  • 41
  • 80

3 Answers3

77

If your deployment target is iOS 6.0 or later

You can simply implement the shouldPerformSegueWithIdentifier:sender: method on your source view controller. Make this method return YES if you want to perform the segue, or NO if you don't.

If your deployment target is earlier than iOS 6.0

You will need to change the way your segue is connected in the storyboard and write a little more code.

First, set up the segue from the button's view controller to the destination view controller, instead of directly from the button to the destination. Give the segue an identifier like ValidationSucceeded.

Then, connect the button to an action on its view controller. In the action, perform the validation and either perform the segue or show an alert based on whether the validation succeeded. It will look something like this:

- (IBAction)performSegueIfValid:(id)sender {
    if ([self validationIsSuccessful]) {
        [self performSegueWithIdentifier:@"ValidationSucceeded" sender:self];
    } else {
        [self showAlertForValidationFailure];
    }
}
rob mayoff
  • 375,296
  • 67
  • 796
  • 848
  • 3
    Its not in the documentation, but it appears that performSegueWithIdentifier:sender: does not call shouldPerformSegueWithIdentifier:sender:. So if you are programmatically triggering a segue, you should also programmatically check shouldPerformSegueWithIdentifier:sender: before doing so. – Richard Venable Nov 14 '14 at 12:53
38

What worked for me and what I believe to be the correct answer is to use UIViewController method found in Apple Developer Guide:

shouldPerformSegueWithIdentifier:sender:

I implemented my method like so:

- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender {
    if ([identifier isEqualToString:@"Identifier Of Segue Under Scrutiny"]) {
        // perform your computation to determine whether segue should occur

        BOOL segueShouldOccur = YES|NO; // you determine this
        if (!segueShouldOccur) {
            UIAlertView *notPermitted = [[UIAlertView alloc] 
                                initWithTitle:@"Alert" 
                                message:@"Segue not permitted (better message here)" 
                                delegate:nil 
                                cancelButtonTitle:@"OK" 
                                otherButtonTitles:nil];

            // shows alert to user
            [notPermitted show];

            // prevent segue from occurring 
            return NO;
        }
    }

    // by default perform the segue transition
    return YES;
}

Worked like a charm!


Updated with Swift for >= iOS 8:

override func shouldPerformSegueWithIdentifier(identifier: String!, sender: AnyObject!) -> Bool {
    if identifier == "Identifier Of Segue Under Scrutiny" {
        // perform your computation to determine whether segue should occur

        let segueShouldOccur = true || false // you determine this
        if !segueShouldOccur {
            let notPermitted = UIAlertView(title: "Alert", message: "Segue not permitted (better message here)", delegate: nil, cancelButtonTitle: "OK")

            // shows alert to user
            notPermitted.show()

             // prevent segue from occurring
            return false
        }
    }

    // by default perform the segue transitio
    return true
}
App Dev Guy
  • 5,396
  • 4
  • 31
  • 54
Shaun
  • 1,539
  • 1
  • 12
  • 11
  • does the usage of performSegueIfValid() have any downside? – Firdous Sep 28 '12 at 06:36
  • I believe it's a user-defined method (did not find it in docs) ...so I didn't try it. But the way I see it, from a design perspective it's not ideal to to be using storyboard segues, but redirecting the connections from their typical outlets to accommodate a feature. – Shaun Sep 28 '12 at 06:38
  • 4
    shouldPerformSegueWithIdentifier:sender: is available since iOS 6, and will not be called from iOS 5. – levigroker Oct 22 '12 at 16:22
  • For newbies. To find the segue identifier in interface builder, open storyboard -> select scene (on left), select the segue (on left) in the scene, then on right, select attributes inspector. Use the Identifier field. – Nick N Apr 02 '13 at 18:45
  • This is the better solution - should be top. – GuybrushThreepwood Jan 15 '14 at 10:31
  • Can this be used when using a Show segue (known as Push segue in iOS 7 and before), to stop the unwind segue that is provided with a UINavigationController? I've tried but couldn't make it work. I want to stop that unwind. – alondono Nov 24 '14 at 12:43
  • Do you have any idea why it is not called. I need to call `self.shouldPerformSegueWithIdentifier` myself – osrl Jan 08 '15 at 12:16
  • @ osrl If you are calling performSegueWithIdentifier programmatically, I believe shouldPerformSegueWithIdentifier does not get called (by design). I'm having difficulty finding Apple documentation to support this though. See post: http://stackoverflow.com/questions/26946566/calling-performseguewithidentifier-doesnt-call-shouldperformseguewithidentifier – Shaun Jan 08 '15 at 23:08
  • Can't get it working with UIAlertController. App just crashes. – Shmidt Feb 02 '16 at 21:02
0

I'll give you an example, here's my code:

- (IBAction)Authentificate:(id)sender {
if([self WSAuthentification]){
   [self performSegueWithIdentifier:@"authentificationSegue" sender:sender];
}
else
{
    UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Authetification Failed" message:@"Please check your Identifications" delegate:self cancelButtonTitle:@"Dismiss" otherButtonTitles:nil, nil];
    [alert show];
}

But it seems that's not working, in all cases my segue is performed. The answer is easy, we have to wire the segue from the view controller it self not from the Button.

Ali
  • 647
  • 2
  • 10
  • 28