Вызов функции executeSeguewIdentifier не вызывает ifperformseguewithIdentifier

У меня есть два контроллера вида. В контроллере просмотра1 у меня есть следующее:

  • a segue, который выводит меня на viewcontroller2 - этот segue называется "showme" и прикрепляется к viewcontroller
  • IBAction для UIButton

В моем коде у меня есть следующие кнопки для нажатия кнопки

@IBAction func buttonPress(sender: AnyObject) {
    println("button pressed")
        performSegueWithIdentifier("showme", sender: self)
}

У меня также есть следующий метод:

override func shouldPerformSegueWithIdentifier(identifier: String?, sender: AnyObject?) -> Bool {
    println("Should performing....")
    return true
}   

По какой-то причине функция shouldPerformSegueWithIdentifier никогда не вызывается. Если, однако, я добавляю segue непосредственно на UIButton в ViewController2, это так.

Я подтвердил, что вызов этого направления в действии моей кнопки работает (см. ниже), но я не понимаю, как это работает. То же самое можно сказать и о подготовке forSegue..

@IBAction func buttonPress(sender: AnyObject) {
    println("button pressed")
    if (shouldPerformSegueWithIdentifier("showme", sender: self)){
        performSegueWithIdentifier("showme", sender: self)}
} 

Ответ 1

Такое поведение совершенно естественно по следующим причинам:

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

2) Когда вы вызываете performSegueWithIdentifier самостоятельно, shouldPerformSegueWithIdentifier не вызывается, поскольку можно предположить, что вы знаете, что делаете. Не было бы никакого смысла в вызове performSegueWithIdentifier но затем возвращал бы NO из shouldPerformSegueWithIdentifier.

Ответ 2

Ответ на

@nburk абсолютно правильный.

Однако я понимаю, что в некоторых ситуациях было бы полезно, если бы shouldPerformSegueWithIdentifier:sender: был вызван в любом случае, также когда вызов в performSegueWithIdentifier:sender: производится в коде.

Например, мы хотим сделать некоторые валидации, чтобы решить, выполняете ли вы segue или нет, и мы хотим сохранить эту логику в одном месте, а не дублировать все условия места, такие как:

if (self.shouldPerformSegue) {
     [self performSegueWithIdentifier:identifier sender:sender];
}

Это легко можно сделать, переопределяя performSegueWithIdentifier:sender: следующим образом:

- (void)performSegueWithIdentifier:(NSString *)identifier sender:(id)sender
{
    if ([self shouldPerformSegueWithIdentifier:identifier sender:sender]) {
        [super performSegueWithIdentifier:identifier sender:sender];
    }
    // otherwise do nothing
}

- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
{
    return self.shouldPerformSegue;
}

Таким образом, вы можете использовать shouldPerformSegueWithIdentifier:sender:, чтобы определить свою логику, чтобы разрешить/запретить как IB, так и код, вызванные segues.

Ответ 3

Как ответ выше. Если вы вызываете performSegueWithIdentifier, то shouldPerformSegueWithIdentifier не вызывается.

В качестве примера:

Допустим, у вас есть встроенный segue внутри контейнера, чтобы показать некоторые изображения, которые вы можете пронести. И встроенные segues запускаются сразу же после загрузки VC. Но если вам нужно будет загружать изображения из удаленного API, ваше приложение потерпит крах, так как не будет никаких изображений для отображения во встроенном представлении segue/container.

В этом случае понадобится shouldPerformSegueWithIdentifier.

Вы можете настроить логическое значение, которое вы проверяете в shouldPerformSegueWithIdentifier, если его ложное возвращение false и ваш сеанс не будут запущены. И как только ваше приложение загрузило изображения, вы могли бы вызвать performSegueWithIdentifier

Ответ 4

если вы используете этот код, который нужно удалить;

[self performSegueWithIdentifier:name sender:sender];

Ответ 5

Спасибо @tanzolone за идеальное решение. Переписал код на Swift 5.

Чтобы принудительно позвонить shouldPerformSegue перед тем performingSegue, вы можете переопределить performingSegue в вас классе:

override func performSegue(withIdentifier identifier: String, sender: Any?) {
    if shouldPerformSegue(withIdentifier: identifier, sender: sender) {
        super.performSegue(withIdentifier: identifier, sender: sender)
    }
}

override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
    // Your code (return true if you want to perform the segue)
}