Question

C'est peut-être une question très simple mais qui n'a donné aucun résultat lors de sa recherche, alors la voici...

J'essaie de trouver un moyen de vérifier si un certain contrôleur de vue peut effectuer une transition avec l'identifiant XYZ avant d'appeler le performSegueWithIdentifier: méthode.

Quelque chose du genre :

if ([self canPerformSegueWithIdentifier:@"SegueID"])
    [self performSegueWithIdentifier:@"SegueID"];

Possible?

Était-ce utile?

La solution

Comme indiqué dans la documentation :

Les applications n’ont normalement pas besoin de déclencher directement des séquences.Au lieu de cela, vous configurez un objet dans Interface Builder associé au contrôleur de vue, tel qu'un contrôle intégré dans sa hiérarchie de vue, pour déclencher la transmission.Cependant, vous pouvez appeler cette méthode pour déclencher une séquence par programme, peut-être en réponse à une action qui ne peut pas être spécifiée dans le fichier de ressources Storyboard.Par exemple, vous pouvez l'appeler à partir d'un gestionnaire d'action personnalisé utilisé pour traiter les événements Shake ou Acceleromment.

Le contrôleur de vue qui reçoit ce message doit avoir été chargé à partir d'un storyboard.Si le contrôleur de vue n'a pas de storyboard associé, peut-être parce que vous l'avez alloué et initialisé vous-même, cette méthode lance une exception.

Ceci étant dit, lorsque vous déclenchez le segue, normalement c'est parce qu'on suppose que le UIViewController sera en mesure d'y répondre avec un segue's identifiant.Je suis également d'accord avec Dan F, vous devriez essayer d'éviter les situations où une exception pourrait être levée.Voici la raison pour laquelle vous ne pouvez pas faire quelque chose comme ceci :

if ([self canPerformSegueWithIdentifier:@"SegueID"])
    [self performSegueWithIdentifier:@"SegueID"];

Je suppose que :

  1. respondsToSelector: vérifie uniquement si vous êtes capable de gérer ce message au moment de l'exécution.Dans ce cas, vous pouvez, car la classe UIViewController est capable de répondre à performSegueWithIdentifier:sender:.Pour réellement vérifier si une méthode est capable de gérer un message avec certains paramètres, je suppose que ce serait impossible, car pour déterminer si c'est possible, elle doit réellement l'exécuter et, ce faisant, le NSInvalidArgumentException va augmenter.
  2. Pour créer réellement ce que vous avez suggéré, il serait utile de recevoir une liste des identifiants de séquence que le UIViewController est associée à.Du UIViewController Documentation, je n'ai rien trouvé qui ressemble à ça

Pour l'instant, je suppose que votre meilleur pari est de continuer avec le @try @catch @finally.

Autres conseils

Pour vérifier si la SEGUE existait ou non, j'ai simplement entouré l'appel avec un bloc de try-and-attraper.Veuillez consulter l'exemple de code ci-dessous:

@try {
    [self performSegueWithIdentifier:[dictionary valueForKey:@"segue"] sender:self];
}
@catch (NSException *exception) {
    NSLog(@"Segue not found: %@", exception);
}

J'espère que cela aide.

- (BOOL)canPerformSegueWithIdentifier:(NSString *)identifier
{
    NSArray *segueTemplates = [self valueForKey:@"storyboardSegueTemplates"];
    NSArray *filteredArray = [segueTemplates filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"identifier = %@", identifier]];
    return filteredArray.count>0;
}

Cet article a été mis à jour pour SWIFT 4.


Voici un plus correct Swift Way de vérifier si une SEGUE existe:

extension UIViewController {
func canPerformSegue(withIdentifier id: String) -> Bool {
        guard let segues = self.value(forKey: "storyboardSegueTemplates") as? [NSObject] else { return false }
        return segues.first { $0.value(forKey: "identifier") as? String == id } != nil
    }

    /// Performs segue with passed identifier, if self can perform it.
    func performSegueIfPossible(id: String?, sender: AnyObject? = nil) {
        guard let id = id, canPerformSegue(withIdentifier: id) else { return }
        self.performSegue(withIdentifier: id, sender: sender)
    }
}

// 1
if canPerformSegue("test") {
    performSegueIfPossible(id: "test") // or with sender: , sender: ...)
}

// 2
performSegueIfPossible(id: "test") // or with sender: , sender: ...)

Vous pouvez remplacer le - (BOOL) DépendeurformsewithIdentifier: expéditeur: méthode et faire votre logique là-bas.

- (BOOL) shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender {
    if ([identifier isEqualToString:@"someSegue"]) {
        if (!canIPerformSegue) {
            return NO;
        }
    }
    return YES;    
}

J'espère que cela aide.

CANPERFORFERGUE.SWIFT

import UIKit

extension UIViewController{
    func canPerformSegue(identifier: String) -> Bool {
        guard let identifiers = value(forKey: "storyboardSegueTemplates") as? [NSObject] else {
            return false
        }
        let canPerform = identifiers.contains { (object) -> Bool in
            if let id = object.value(forKey: "_identifier") as? String {
                return id == identifier
            }else{
                return false
            }
        }
        return canPerform
    }
}

Version Swift de la réponse de Evgeny Mikhaylov, qui a fonctionné pour moi:

Je réutilise un contrôleur pour deux vues.Cela aide-moi à réutiliser le code.

if(canPerformSegueWithIdentifier("segueFoo")) {
  self.performSegueWithIdentifier("segueFoo", sender: nil)
}
else {
  self.performSegueWithIdentifier("segueBar", sender: nil)
}


func canPerformSegueWithIdentifier(identifier: NSString) -> Bool {
    let templates:NSArray = self.valueForKey("storyboardSegueTemplates") as! NSArray
    let predicate:NSPredicate = NSPredicate(format: "identifier=%@", identifier)

    let filteredtemplates = templates.filteredArrayUsingPredicate(predicate)
    return (filteredtemplates.count>0)
}

Il n'y a aucun moyen de vérifier qu'en utilisant les fonctions standard, ce que vous pouvez faire est de sous-classer UIStoryboardSegue et stocker les informations dans le source contrôleur de vue (qui est passé au constructeur).Dans le générateur d'interface, sélectionnez "Personnalisé" comme type de séquence et tapez le nom de classe de votre séquence, puis votre constructeur sera appelé pour chaque séquence instanciée et vous pourrez interroger les données stockées si elles existent.

Vous devez également remplacer le perform méthode pour appeler [source presentModalViewController:destination animated:YES] ou [source pushViewController:destination animated:YES] selon le type de transition souhaité.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top