Как сделать что-то перед тем, как отменить действие segue?

Я только что понял, что такое развязать segue и как использовать его с замечательными ответами из этого вопроса. Большое спасибо.

Однако здесь возникает вопрос:

Скажем, есть кнопка в сцене B, которая разматывает сцены на сцену A, и перед этим segues я хочу, чтобы что-то было сделано, например, сохранение данных в базу данных. Я создал действие для этой кнопки в B.swift, но кажется, что он идет непосредственно на сцену A без принятия назначенного действия.

Кто-нибудь знает, почему и как это сделать?

Спасибо.

Ответы

Ответ 1

Вы можете сделать это так, как вы описали, или с помощью функции переопределения prepareForSegue в диспетчере viewController, из которого вы освобождаетесь:

@IBAction func actionForUnwindButton(sender: AnyObject) {
    println("actionForUnwindButton");
}

или...

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    println("prepareForSegue");
}

Первый пример, как вы описали. Кнопка подключена к развязке и к действию кнопки в Interface Builder. Действие кнопки будет активировано перед действием segue. Возможно, вы не подключили действие к кнопке в построителе интерфейса?

Второй пример дает вам доступ к segue sourceViewController и destinationViewController в том случае, если это также полезно (вы также получаете их в функции размотки segue в контроллере представления назначения).

Если вы хотите отложить разматывание до тех пор, пока локальное действие кнопки не будет завершено, вы можете вызвать segue непосредственно из действия кнопки (вместо того, чтобы подключаться к ней в раскадровке) с помощью self.performSegueWithIdentifier (или следовать предложению wrUS61)

ИЗМЕНИТЬ

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

class BlueViewController: UIViewController {

    @IBAction func actionForUnwindButton(sender: AnyObject) {
        println("actionForUnwindButton");
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        println("prepareForSegue");
    }
}


class RedViewController: UIViewController {

    @IBAction func unwindToRed(sender: UIStoryboardSegue) {
        println("unwindToRed");
    }
}

В BlueViewController есть кнопка, которая подключена в раскадровке к BOTH кнопке unwindToRed разматывать и actionForUnwindButton. Он также переопределяет prepareForSegue, чтобы мы могли зарегистрировать порядок воспроизведения.

Вывод:

actionForUnwindButton
prepareForSegue
unwindToRed

Раскадровка:

enter image description here

РЕДАКТИРОВАТЬ 2

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

(A) UIButton в контроллере просмотра

Кнопка ViewController получает touchupInside
- (1) отправляет действие этому методу
- (2) отправляет segue разматывать действие в раскадровку segue
все полученные сообщения и методы, выполненные в следующем порядке:

actionForUnwindButton
prepareForSegue
unwindToRed

(B) UIBarButtonItem в панели инструментов навигационного контроллера

Кнопка панели инструментовItem получает touchupInside
- (1) отправляет segue разматывать действия в раскадровку segue
- (2) (возможно, затем) отправляет действие viewController method

Порядок выполнения

prepareForSegue
unwindToRed
actionForUnwindButton

prepareForSegue и unwind полученных сообщений. Однако сообщение actionForUnwindButton отправляется в nil, поскольку viewController уничтожается во время сеанса. Таким образом, он не выполняется, а журнал печатает

prepareForSegue
unwindToRed

В случае (B), viewController уничтожается до того, как метод достигает его, поэтому не запускается

Итак, ваши варианты... (a) использовать UIButton с действием и разматывать segue
(b) инициируйте свои действия с помощью prepareForSegue, который будет запущен, пока viewController все еще жив, и до того, как произойдет segue.
(c) не используйте разматывающий сегмент, просто используйте действие кнопки. В методе действий вы можете "расслабиться", вызвав popToViewController на вашем навигационном контроллере.

Кстати, если вы реализуете toolBar на viewController (не используя панель управления навигационным контроллером), результат будет таким же: сначала запускается segue, поэтому действие кнопки не выполняется.

enter image description here

Ответ 2

Если вы можете успешно выполнить команду "Отключить Segue". Затем метод в представлении View Controller вызывается непосредственно перед тем, как произойдет segue, вы можете делать то, что вы хотите, в source viewcontroller, используя объект segue.

- (IBAction)unwindToThisViewController:(UIStoryboardSegue *)unwindSegue
{
  CustomViewController *vc = (CustomViewController*) unwindSegue.sourceViewController;
  [vc performAnyMethod];
  [vc saveData];
  NSString *temp = vc.anyProperty;

}

если вы хотите, чтобы ваша логика в исходном контроллере затем реализовала prepareForSegue в Scene B и установила идентификатор UnWind segue Identifier из раскадровки > Панель иерархии Left View > в разделе Exit in Scene B.

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if([[segue identifier] isEqualToString:@"backToSource"])
    {
        NSLog(@"Going Back");

    }
}

Ответ 3

Сначала вы должны вызвать функцию отправки данных в методе prepareForSegue.

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if([[segue identifier] isEqualToString:@"UnwindIdentifier"]) {
        // send data
    }
}

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

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

и return NO;. Затем вы можете выполнить segue вручную, когда получите ответ сервера, вызвав:

[self performSegueWithIdentifier:@"UnwindIdentifier" sender:sender];