web-dev-qa-db-fra.com

L'appel de performSeguewithIdentifier n'appelle pas shouldperformsegueguewithIdentifier

J'ai deux contrôleurs de vue. Sur la vue controller1, j'ai les informations suivantes:

  • une séquence qui m'amène à viewcontroller2 - cette séquence est nommée "showme" et est attachée au viewcontroller
  • une IBAction pour un UIButton

Dans mon code, j'ai ce qui suit pour l'action de pression sur le bouton

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

J'ai également la méthode suivante:

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

Pour une raison quelconque, la fonction shouldPerformSegueWithIdentifier n'est jamais appelée. Si cependant, j'ajoute le segue directement sur le UIButton à ViewController2 c'est.

J'ai confirmé que l'appeler direction dans l'action de mon bouton fonctionne (voir ci-dessous), mais ce n'est pas ce que je comprends être la façon dont cela fonctionne. Il en va de même pour prepareforSegue ..

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

Ce comportement est parfaitement naturel, pour les raisons suivantes:

1) shouldPerformSegueWithIdentifier est utilisé pour s'assurer qu'un enchaînement qui a été configuré dans Storyboards doit être déclenché, donc il n'est appelé que dans le cas de Storyboard Segues et vous donne la chance de pas effectuez réellement la séquence.

2) Lorsque vous appelez performSegueWithIdentifier vous-même, shouldPerformSegueWithIdentifier n'est pas appelé car on peut supposer que vous savez ce que vous faites. Il serait inutile d'appeler performSegueWithIdentifier mais de renvoyer un NO de shouldPerformSegueWithIdentifier.

76
nburk

La réponse @nburk est absolument correcte.

Cependant, je comprends que dans certaines situations, il pourrait être utile que shouldPerformSegueWithIdentifier:sender: serait appelé de toute façon, même lorsqu'un appel à performSegueWithIdentifier:sender: est fait en code.

Par exemple, nous voulons faire des validations pour décider si effectuer une séquence ou non et nous voulons garder cette logique en un seul endroit et ne pas dupliquer partout les conditions de lieu comme les suivantes:

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

Ceci peut être facilement réalisé en remplaçant performSegueWithIdentifier:sender: comme suit:

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

De cette façon, vous pouvez utiliser shouldPerformSegueWithIdentifier:sender: pour définir votre logique afin d'autoriser/refuser à la fois les séquences déclenchées par IB et par code.

29
tanzolone

Comme la réponse ci-dessus. Si vous appelez performSegueWithIdentifier alors shouldPerformSegueWithIdentifier n'est pas appelé.

Par exemple:

Disons que vous avez un enchaînement intégré à l'intérieur d'une vue de conteneur afin d'afficher des images que vous pouvez parcourir. Et les séquences intégrées sont tirées immédiatement lorsque vous VC a été chargé. Mais si vous deviez télécharger les images à partir d'une API distante, votre application se bloquerait car il n'y aurait aucune image à afficher dans la solution intégrée). vue segue/container.

Dans ce cas, shouldPerformSegueWithIdentifier serait nécessaire.

Vous pouvez configurer une valeur booléenne que vous archivez shouldPerformSegueWithIdentifier si son faux retour est faux et que votre séquence ne sera pas renvoyée. Et une fois que votre application a téléchargé les images que vous pourriez appeler performSegueWithIdentifier

3
user2722667

Merci @tanzolone pour la solution parfaite. Code réécrit sur Swift 5.

Pour appeler avec force shouldPerformSegue avant performingSegue, vous pouvez remplacer performingSegue dans votre classe:

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)
}
0
Vergiliy

si vous utilisez ce code, vous devez le supprimer;

[self performSegueWithIdentifier:name sender:sender];

0
alicanozkara