Предотвратить переход в методе prepareForSegue? - PullRequest
245 голосов
/ 09 ноября 2011

Можно ли отменить переход в методе prepareForSegue:?

Я хочу выполнить некоторую проверку перед переходом, и если условие не выполнено (в этом случае, если некоторое значение UITextField пусто), вместо сообщения перейдите к сообщению об ошибке.

Ответы [ 10 ]

475 голосов
/ 10 октября 2012

Это возможно в iOS 6 и более поздних версиях: вам нужно реализовать метод

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

в вашем контроллере вида.Вы делаете свою проверку там, и если все в порядке, тогда return YES;, если это не так, тогда return NO;, и prepareForSegue не вызывается.

Обратите внимание, что этот метод не вызывается автоматически при программном запуске сегментов.Если вам нужно выполнить проверку, то вы должны вызвать shouldPerformSegueWithIdentifier, чтобы определить, следует ли выполнять переход.

51 голосов
/ 09 ноября 2011

Примечание: принятый ответ - лучший подход, если вы можете настроить таргетинг на iOS 6. Для таргетинга на iOS 5 этот ответ подойдет.

Я не верю, что это возможноотменить переход в prepareForSegue.Я бы предложил перенести вашу логику так, чтобы сначала отправлялось сообщение performSegue.

Если вы используете Interface Builder для соединения перехода непосредственно с элементом управления (например, связывание перехода непосредственно с UIButton), тогда вы можете сделать это с помощью небольшого рефакторинга.Подключите переход к контроллеру представления вместо определенного элемента управления (удалите старую ссылку перехода, а затем перетащите элемент управления из самого контроллера представления в целевой контроллер представления).Затем создайте IBAction в вашем контроллере вида и подключите элемент управления к IBAction.Затем вы можете выполнить свою логику (проверить наличие пустого TextField) в только что созданном IBAction и решить, стоит ли performSegueWithIdentifier программно.

14 голосов
/ 30 сентября 2016

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

Возвращаемое значение true ifпереход следует выполнить или 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
}
12 голосов
/ 25 ноября 2011

Альтернативно, несколько плохое поведение - предлагать кнопку, которую пользователь не должен нажимать.Вы можете оставить переход подключенным как стенды, но начать с отключенной кнопки.Затем подключите UITextField «editChanged» к событию в элементе управления представлением

- (IBAction)nameChanged:(id)sender {
    UITextField *text = (UITextField*)sender;
    [nextButton setEnabled:(text.text.length != 0)];
}
11 голосов
/ 27 октября 2015

Легко и быстро.

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

    return true
}
9 голосов
/ 30 ноября 2015

Как сказал Авраам, проверка действительна или нет в следующей функции.

- (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];
}
5 голосов
/ 06 июля 2015

должен выполнить переход для входа в систему Регистрация

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

}
4 голосов
/ 10 июля 2018

Swift 4 Ответ:

Ниже приведена реализация 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
}
4 голосов
/ 30 августа 2012

Аналогично ответу Каолина - оставить след, привязанный к элементу управления, но проверить элемент управления на основе условий в представлении.Если вы используете взаимодействие с ячейками таблицы, вам также нужно установить свойство 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;
    }

}
2 голосов
/ 10 февраля 2017

Другой способ - переопределить метод tableView с помощью willSelectRowAt и вернуть nil, если вы не хотите показывать результат. showDetails() - это какой-то бул. В большинстве случаев должна быть реализована модель данных, представленная в ячейке с indexPath.

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