wake-up-neo.com

Segue in prepareForSegue-Methode verhindern?

Kann ein Segue mit der Methode prepareForSegue: Abgebrochen werden?

Ich möchte vor dem Segue eine Überprüfung durchführen. Wenn die Bedingung nicht erfüllt ist (in diesem Fall, wenn einige UITextField leer sind), wird eine Fehlermeldung angezeigt, anstatt das Segue auszuführen.

247
Shmidt

Ab iOS 6 ist es möglich: Sie müssen die Methode implementieren

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

In Ihrem View Controller. Sie machen Ihre Validierung dort und wenn es in Ordnung ist, dann return YES; wenn es nicht ist, dann return NO; und prepareForSegue wird nicht aufgerufen.

Beachten Sie, dass diese Methode beim programmgesteuerten Auslösen von Segues nicht automatisch aufgerufen wird. Wenn Sie die Prüfung durchführen müssen, müssen Sie shouldPerformSegueWithIdentifier aufrufen, um zu bestimmen, ob eine Segue-Prüfung durchgeführt werden soll.

477
Abraham

Hinweis: Die akzeptierte Antwort ist der beste Ansatz, wenn Sie iOS 6 als Ziel festlegen können. Für iOS 5 reicht diese Antwort aus.

Ich glaube nicht, dass es möglich ist, eine Übergabe in prepareForSegue abzubrechen. Ich würde vorschlagen, Ihre Logik so weit zu verschieben, dass die Nachricht performSegue zuerst gesendet wird.

Wenn Sie mit Interface Builder einen Abschnitt direkt mit einem Steuerelement verbinden (z. B. einen Abschnitt direkt mit einem UIButton verknüpfen), können Sie dies mit ein wenig Umgestaltung erreichen. Verbinden Sie das Segment mit dem Ansichts-Controller anstelle eines bestimmten Steuerelements (löschen Sie den alten Segment-Link und ziehen Sie ihn mit gedrückter Strg-Taste vom Ansichts-Controller selbst zum Ziel-Ansichts-Controller). Erstellen Sie dann ein IBAction in Ihrem View-Controller und verbinden Sie das Steuerelement mit der IBAction. Dann können Sie Ihre Logik (auf leeres TextField prüfen) in der soeben erstellten IBAction ausführen und dort entscheiden, ob Sie performSegueWithIdentifier programmgesteuert ausführen möchten oder nicht.

51
Mike Mertsock

Swift: func shouldPerformSegue (withIdentifier identifier: String, sender: Any?) -> Bool

Rückgabewert true wenn das Segue ausgeführt werden soll oder false wenn es ignoriert werden soll.

Beispiel:

var badParameters:Bool = true

override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
    if badParameters  {
         // your code here, like badParameters  = false, e.t.c
         return false
    }
    return true
}
15
OrdoDei

Alternativ ist es etwas schlecht, eine Taste anzubieten, die ein Benutzer nicht drücken sollte. Sie können die Verdrahtung des Segues beibehalten, aber mit deaktivierter Schaltfläche beginnen. Verbinden Sie dann das "editingChanged" von UITextField mit einem Ereignis auf dem Ansichtssteuerelement

- (IBAction)nameChanged:(id)sender {
    UITextField *text = (UITextField*)sender;
    [nextButton setEnabled:(text.text.length != 0)];
}
12
Kaolin Fire

Es ist einfach in der Swift.

override func shouldPerformSegueWithIdentifier(identifier: String,sender: AnyObject?) -> Bool {

    return true
}
11
Zumry Mohamed

Wie Abraham sagte, Überprüfe, ob die folgende Funktion gültig ist oder nicht.

- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(nullable id)sender
{
     // Check this identifier is OK or NOT.
}

Und das performSegueWithIdentifier:sender:, das durch Programmierung aufgerufen wird, kann durch Überschreiben der folgenden Methode blockiert werden. Standardmäßig überprüft es nicht gültig oder nicht von -shouldPerformSegueWithIdentifier:sender:, wir können es manuell machen.

- (void)performSegueWithIdentifier:(NSString *)identifier sender:(id)sender
{
    // Check valid by codes
    if ([self shouldPerformSegueWithIdentifier:identifier sender:sender] == NO) {
        return;
    }

    // If this identifier is OK, call `super` method for `-prepareForSegue:sender:` 
    [super performSegueWithIdentifier:identifier sender:sender];
}
9
AechoLiu

Sollte Segue for Login Register ausführen

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

    [self getDetails];

    if ([identifier isEqualToString:@"loginSegue"])
    {

        if (([_userNameTxtf.text isEqualToString:_uname])&&([_passWordTxtf.text isEqualToString:_upass]))
        {

            [email protected]"";
            [email protected]"";

            return YES;
        }
        else
        {
            UIAlertView *loginAlert = [[UIAlertView alloc] initWithTitle:@"Alert" message:@"Invalid Details" delegate:self cancelButtonTitle:@"Try Again" otherButtonTitles:nil];

            [loginAlert show];

            [email protected]"";
            [email protected]"";

            return NO;
        }

    }

    return YES;

}

-(void)getDetails
{
    NSArray *dir=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

    NSString *dbpath=[NSString stringWithFormat:@"%@/userDb.sqlite",[dir lastObject]];

    sqlite3 *db;

    if(sqlite3_open([dbpath UTF8String],&db)!=SQLITE_OK)
    {
        NSLog(@"Fail to open datadbase.....");
        return;
    }

    NSString *query=[NSString stringWithFormat:@"select * from user where userName = \"%@\"",_userNameTxtf.text];

    const char *q=[query UTF8String];

    sqlite3_stmt *mystmt;

    sqlite3_prepare(db, q, -1, &mystmt, NULL);

    while (sqlite3_step(mystmt)==SQLITE_ROW)
    {
        _uname=[NSString stringWithFormat:@"%s",sqlite3_column_text(mystmt, 0)];

        _upass=[NSString stringWithFormat:@"%s",sqlite3_column_text(mystmt, 2)];
    }

    sqlite3_finalize(mystmt);
    sqlite3_close(db);

}
5
Swappyee

Swift 4 Antwort:

Es folgt die Implementierung von Swift 4, um die Übergabe abzubrechen:

override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
    if identifier == "EditProfile" {
        if userNotLoggedIn {
            // Return false to cancel segue with identified Edit Profile
            return false
        }
    }
    return true
}
4
Pankaj Kulkarni

Ähnlich wie bei Kaolin besteht die Antwort darin, die Seque mit der Steuerung verbunden zu lassen, die Steuerung jedoch anhand der Bedingungen in der Ansicht zu validieren. Wenn Sie eine Interaktion mit Tabellenzellen auslösen, müssen Sie auch die Eigenschaft userInteractionEnabled festlegen und die Inhalte in der Zelle deaktivieren.

Zum Beispiel habe ich ein Formular in einer gruppierten Tabellenansicht. Eine der Zellen führt zu einer anderen tableView, die als Picker fungiert. Immer wenn ein Steuerelement in der Hauptansicht geändert wird, rufe ich diese Methode auf

-(void)validateFilterPicker
{
    if (micSwitch.on)
    {
        filterPickerCell.textLabel.enabled = YES;
        filterPickerCell.detailTextLabel.enabled = YES;
        filterPickerCell.userInteractionEnabled = YES;
        filterPickerCell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    }
    else
    {
        filterPickerCell.textLabel.enabled = NO;
        filterPickerCell.detailTextLabel.enabled = NO;
        filterPickerCell.userInteractionEnabled = NO;
        filterPickerCell.accessoryType = UITableViewCellAccessoryNone;
    }

}
4
James Moore

Die andere Möglichkeit besteht darin, die Methode von tableView mit willSelectRowAt zu überschreiben und nil zurückzugeben, wenn Sie den Segue nicht anzeigen möchten. showDetails() - ist ein Trottel. In den meisten Fällen sollte das Datenmodell in einer Zelle mit indexPath dargestellt werden.

 func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
        if showDetails() {
                return indexPath            
        }
        return nil
    }
2
Bogdan Ustyak