是否可以在prepareForSegue:方法中取消一个segue ?

我想在segue之前执行一些检查,如果条件不为真(在这种情况下,如果一些UITextField为空),显示一个错误消息而不是执行segue。


当前回答

是否应该为登录寄存器执行Segue

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

    [self getDetails];

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

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

            _userNameTxtf.text=@"";
            _passWordTxtf.text=@"";

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

            [loginAlert show];

            _userNameTxtf.text=@"";
            _passWordTxtf.text=@"";

            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);

}

其他回答

与Kaolin的答案类似,将seque连接到控件,但根据视图中的条件验证控件。如果你在表格单元格交互上触发,那么你还需要设置userInteractionEnabled属性以及禁用单元格中的东西。

例如,我在分组表视图中有一个表单。其中一个单元格指向另一个作为选择器的tableView。每当一个控件在主视图中被改变时,我就调用这个方法

-(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;
    }

}

正如亚伯拉罕所说,在下面的函数中检查有效与否。

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

并且,通过编程调用的performSegueWithIdentifier:sender:可以通过覆盖下面的方法来阻止。默认情况下,它不会通过-shouldPerformSegueWithIdentifier:sender:检查是否有效,我们可以手动执行。

- (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];
}

另一种方法是用willSelectRowAt重写tableView的method如果你不想显示segue,就返回nil。 showDetails() -是一些bool值。在大多数情况下,应该在数据模型中实现,用indexPath表示在单元格中。

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

另外,提供一个用户不应该按的按钮是一种坏行为。您可以将segue设置为stand,但在开始时禁用该按钮。然后将UITextField的“editingChanged”连接到视图控件上的一个事件

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

注意:如果你的目标是iOS 6,那么接受的答案是最好的方法。针对iOS 5,这个答案就可以了。

我不相信在prepareForSegue中可以取消segue。我建议将您的逻辑移到performSegue消息第一次发送的位置。

If you are using Interface Builder to wire up a segue directly to a control (e.g. linking a segue directly to a UIButton), then you can accomplish this with a bit of refactoring. Wire the segue to the view controller instead of a specific control (delete the old segue link, and then control-drag from the view controller itself to the destination view controller). Then create an IBAction in your view controller, and wire the control to the IBAction. Then you can do your logic (check for empty TextField) in the IBAction you just created, and decide there whether or not to performSegueWithIdentifier programatically.