在prepareForSegue方法中阻止segue ?

是否可以取消prepareForSegue:方法中的segue ?

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

96992 次浏览

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

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

如果你正在使用Interface Builder将segue直接连接到控件(例如,将segue直接链接到UIButton),那么你可以通过一些重构来完成这一点。将segue连接到视图控制器,而不是特定的控件(删除旧的segue链接,然后从视图控制器本身control-drag到目标视图控制器)。然后在视图控制器中创建IBAction,并将该控件连接到IBAction。然后你可以在刚刚创建的IBAction中执行你的逻辑(检查空TextField),并在那里决定是否以编程方式performSegueWithIdentifier

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

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

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


}
这在ios6及以后版本中是可能的: 你必须实现

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

在视图控制器中。你在那里进行验证,如果OK,则return YES;,如果不OK,则return NO;, prepareForSegue不被调用。

注意,当以编程方式触发segue时,不会自动调用此方法。如果你需要执行检查,那么你必须调用shouldPerformSegueWithIdentifier来决定是否执行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);


}

它在快速中很容易。

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


return true
}

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

- (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];
}
< p > 斯威夫特3: shouldPerformSegue(withIdentifier标识符:字符串, sender: Any?) -> Bool

如果需要执行segue,则返回值真正的;如果需要忽略segue,则返回值

例子:

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
}
另一种方法是用willSelectRowAt重写tableView的method,如果你不想显示segue,返回nil。 showDetails() -是一些bool类型。在大多数情况下,应该在数据模型中实现,在单元格中用indexPath表示
 func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
if showDetails() {
return indexPath
}
return nil
}

回答:

下面是Swift 4取消segue的实现:

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
}