255

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

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

4

10 回答 10

494

在 iOS 6 及更高版本中可能:您必须实现该方法

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

在您的视图控制器中。您在那里进行验证,如果可以,那么return YES;如果不是return NO;,则不会调用 prepareForSegue。

请注意,以编程方式触发 segue 时不会自动调用此方法。如果需要执行检查,则必须调用 shouldPerformSegueWithIdentifier 来确定是否执行 segue。

于 2012-10-10T11:34:06.877 回答
53

注意:如果您可以定位 iOS 6,则接受的答案是最好的方法。对于定位 iOS 5,这个答案就可以了。

我不相信有可能取消prepareForSegue. 我建议将您的逻辑移到performSegue第一次发送消息的程度。

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

于 2011-11-09T14:49:09.613 回答
21

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

如果应该执行 segue,则返回值true ;如果应该忽略它,则返回false 。

示例

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
}
于 2016-09-30T13:53:06.670 回答
12

或者,提供一个用户不应该按下的按钮有点不好。您可以将 segue 保留为支架,但从禁用按钮开始。然后将 UITextField 的“editingChanged”连接到视图控件 ala 上的事件

- (IBAction)nameChanged:(id)sender {
    UITextField *text = (UITextField*)sender;
    [nextButton setEnabled:(text.text.length != 0)];
}
于 2011-11-25T00:31:37.563 回答
11

它在 swift 中很容易。

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

    return true
}
于 2015-10-27T03:49:24.497 回答
9

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

- (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];
}
于 2015-11-30T08:03:48.350 回答
6

斯威夫特 4 答案:

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

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
}
于 2018-07-10T15:58:49.390 回答
5

应为登录注册执行 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);

}
于 2015-07-06T07:47:15.700 回答
4

类似于 Kaolin 的答案是将序列连接到控件,但根据视图中的条件验证控件。如果您正在触发表格单元格交互,那么您还需要设置 userInteractionEnabled 属性以及禁用单元格中的内容。

例如,我在分组表视图中有一个表单。One of the cells leads to another tableView that acts as a picker. 每当在主视图中更改控件时,我都会调用此方法

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

}
于 2012-08-30T16:46:39.233 回答
2

另一种方法是使用 willSelectRowAt 覆盖 tableView 的方法,如果您不想显示 segue,则返回 nil。 showDetails()- 是一些布尔值。在大多数情况下,应该在以 . 表示的单元格中表示的数据模型中实现indexPath

 func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
        if showDetails() {
                return indexPath            
        }
        return nil
    }
于 2017-02-10T14:37:03.157 回答