Comment effectuer un déroulement de déroulement par programme?

307

L'utilisation du storyboard est très simple. Vous faites simplement glisser l'action sur "Quitter". Mais comment dois-je l'appeler à partir de mon code?

tadasz
la source
33
Je trouve que c'est une question valable - je l'ai eu moi-même. Vous pouvez effectuer un enchaînement de déroulement par programme 1. en créant un enchaînement manuel (ctrl-glisser du propriétaire du fichier vers Exit), 2. en lui donnant un nom dans IB, puis 3. en faisant un normal -performSegueWithIdentifier: sender: dans votre code.
Yang Meyer
6
N'aurait pas dû être fermé OMI. Les utilisateurs qui ont voté pour fermer cette question ne semblent pas avoir de fond Obj-C / Cocoa Touch.
LJ Wilson
Yang: Comment lui donnez-vous un nom?
sarfata
J'utilise simplement [self disableViewControllerAnimated: YES: nil] pour quitter par programme. Je ne sais pas si c'est une bonne façon ou non.
tangqiaoboy
1
sarfata: Vous créez d'abord un "enchaînement de déroulement manuel" par ctrl-glisser du viewcontroller vers "Exit". Ensuite, vous pouvez trouver la séquence dans le plan du document.
huggie

Réponses:

283
  1. Créer une ctrlséquence manuelle ( -faites glisser le propriétaire du fichier vers la sortie),
  2. Choisissez-le dans le menu gauche du contrôleur sous le bouton vert EXIT.

Choisissez-le dans le menu du contrôleur gauche sous le bouton vert EXIT

Insérez le nom de Segue pour vous détendre.

Ensuite, - (void)performSegueWithIdentifier:(NSString *)identifier sender:(id)sender.avec votre identifiant de séquence.

Vadim
la source
25
1) "Propriétaire du fichier" - n'est-ce pas l'ancienne terminologie? Cela a fonctionné pour moi de contrôler le glissement du contrôleur de vue vers son icône Quitter. 2) Bien que cela doive être évident, Xcode recherche une déclaration dans l'interface de l'IBAction qui prend un argument UIStoryboardSegue; le discours de la session 407 de la WWDC 2012 n'a pas mentionné cela et n'a pas collé ce code. Sans cela, mon icône Quitter ne deviendrait pas active lors du glissement de contrôle. 3) C'est plutôt cool qu'à la fin de votre grosse flèche rouge, dans le champ Action, vous puissiez frapper la flèche "allez-y"!
tobinjim
71
Pour tous ceux qui, comme moi, ont encore du mal à implémenter cette réponse, j'ai mis en place une procédure plus détaillée et un exemple dans ce référentiel : github.com/bradley/iOSUnwindSegueProgramematic (n'essayant pas de m'annoncer , je me suis juste cogné la tête contre le mur pendant des heures et voir une configuration de travail m'aide.)
bradleygriffith
3
@bradleygriffith Vous êtes incroyablement super génial. Merci pour la grande soluce!
Eli_Rozen
7
@bradleygriffith Je souhaite que vous ayez répondu à cette question afin que je puisse le noter aussi! Votre contribution unique a été d'établir quel contrôleur de vue obtient quel code . Je n'ai pu trouver ça nulle part. Merci!
Aaron Vegh
3
La clé, pour quiconque est toujours perplexe à ce sujet, est que l'IBACTION doit être dans le contrôleur de vue vers lequel vous revenez, pas celui dans lequel vous vous trouvez actuellement. @Bradleygriffith l'énonce sur GitHub, mais je ne l'ai pas vu mentionné ailleurs. Cette partie est critique.
Axeva
163

Voici une réponse complète avec Objective C et Swift:

1) Créez un IBActionenchaînement de déroulement dans votre contrôleur de vue de destination (où vous souhaitez effectuer un enchaînement). N'importe où dans le fichier d'implémentation.

// Objective C

    - (IBAction)unwindToContainerVC:(UIStoryboardSegue *)segue {

    }

// Swift

 @IBAction func unwindToContainerVC(segue: UIStoryboardSegue) {

    }

2) Sur le contrôleur de vue source (le contrôleur dont vous effectuez la transition), ⌃ + faites glisser depuis "Nom de l'activité" pour quitter. Vous devriez voir la séquence de déroulement créée à l'étape 1 dans la fenêtre contextuelle. (Si vous ne le voyez pas, passez en revue la première étape). Choisissez unwindToContainerVC: dans la fenêtre contextuelle, ou tout ce que vous avez nommé votre méthode pour connecter votre contrôleur source à l'IBAction dérouler.

entrez la description de l'image ici

3) Sélectionnez la séquence dans le plan du document du contrôleur de vue source du storyboard (il sera répertorié vers le bas) et attribuez-lui un identifiant .

entrez la description de l'image ici

4) Appelez la séquence de déroulement à l'aide de cette méthode à partir du contrôleur de vue source , en remplaçant votre nom de séquence de déroulement.

// Objectif c

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

// Rapide

self.performSegueWithIdentifier("unwindToContainerVC", sender: self)

NB. Utilisez la propriété sourceViewController du paramètre segue sur la méthode de déroulement pour accéder aux propriétés exposées sur le contrôleur source. Notez également que le cadre gère la fermeture du contrôleur source. Si vous souhaitez confirmer cela, ajoutez une méthode de désallocation au contrôleur source avec un message de journal qui devrait se déclencher une fois qu'il a été tué. Si dealloc ne se déclenche pas, vous pouvez avoir un cycle de rétention.

smileBot
la source
2
Mon programme ne fonctionne pas, même pas appelé(IBAction)unwindToContainerVC:(UIStoryboardSegue *)segue
xhg
2
cette solution ne fonctionne pas lorsque le contrôleur de vue, auquel vous vous déroulez, n'existe que dans votre storyboard, alias n'a pas d'implémentation de code personnalisé
mnl
@mnl ne sait pas exactement ce que vous dites, mais cela fonctionne avec des scènes de storyboard ou des plumes. Si vous créez une scène de Viewcontroller dans le code, vous n'utiliserez aucune méthode qui "renverra" IB en son nom, ce qui est vraiment nul de toute façon car elles servent à communiquer entre le code et IB. Est-ce que cela répond à votre commentaire?
smileBot
1
Votre photo montrant le ctrl+dragdu ViewControllerau a Exitété extrêmement utile. Merci!
kbpontius
Pour Swift 4.2, utilisez: self.performSegue (withIdentifier: "unwindToVC", sender: self)
Reefwing
81

bradleygriffithLa réponse a été excellente. J'ai pris l'étape 10 et fait une capture d'écran pour simplifier. Il s'agit d'une capture d'écran dans Xcode 6.

  1. Faites glisser la souris de l'icône orange vers l'icône de sortie rouge pour créer un déroulement sans aucune action / aucun bouton dans la vue.

entrez la description de l'image ici

  1. Sélectionnez ensuite unwind seguedans la barre latérale:

entrez la description de l'image ici

  1. Définissez une chaîne d'identifiant Segue:

entrez la description de l'image ici

  1. Accédez à cet identifiant à partir du code:
[self performSegueWithIdentifier:@"unwindIdentifier" sender:self];
doyen
la source
4
Tout d'abord, la méthode de déroulement doit être incluse à l'intérieur du UIViewController. Ensuite, votre solution fonctionnera
Alex Cio
5
et vous devez définir l'identifiant sur cette nouvelle séquence! N'oubliez pas.
kraag22
1
Est-il possible de créer la connexion "exit" dans le contrôleur de vue source par programmation?
Andrew Kirna
13

J'ai utilisé [self dismissViewControllerAnimated: YES completion: nil];ce qui vous ramènera à l'appel ViewController.

Larry Gibson
la source
6
Larry, c'est une approche parfaitement valable si vous souhaitez revenir au contrôleur de vue précédent, c'est-à-dire celui qui présentait celui que vous quittez maintenant. La question est venue parce que la nouveauté de Xcode 4.5 est la possibilité de se "dérouler" d'un contrôleur de vue quelque part dans l'ordre de présentation vers un contrôleur de vue beaucoup plus ancien. Voir la session 407 de la WWDC 2012 pour plus de détails.
tobinjim
11

Citation du texte de la note technique d'Apple sur la séquence de déroulement: pour ajouter une séquence de déroulement qui ne sera déclenchée que par programme, contrôlez + faites glisser de l'icône du contrôleur de vue de la scène vers son icône de sortie, puis sélectionnez une action de déroulement pour la nouvelle séquence dans le menu contextuel.

Lien vers la note technique

Vishal Chaudhry
la source
6

La réponse de Vishal Chaudhry ci-dessus a fonctionné pour moi. J'ajouterais également cela afin de déclencher manuellement la seque en utilisant:

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

à partir du ViewController, vous devez également sélectionner la séquence de déroulement sous la scène du ViewController dans le storyboard et dans la vue des propriétés sur le RHS, assurez-vous que le champ Indentifier contient le namer auquel vous faites référence dans le code ("mySegueName" dans l'exemple ci-dessus). ).

Si vous omettez cette étape, la ligne ci-dessus lèvera une exception indiquant que le nom de la séquence n'est pas connu.

Jason Crocker
la source
3

Solution rétrocompatible qui fonctionnera pour les versions antérieures à ios6, pour les personnes intéressées:

- (void)unwindToViewControllerOfClass:(Class)vcClass animated:(BOOL)animated {

    for (int i=self.navigationController.viewControllers.count - 1; i >= 0; i--) {
        UIViewController *vc = [self.navigationController.viewControllers objectAtIndex:i];
        if ([vc isKindOfClass:vcClass]) {
            [self.navigationController popToViewController:vc animated:animated];
            return;
        }
    }
}
Joel Teply
la source
2
Les séquences de déroulement font bien plus que revenir à une certaine classe dans une pile de contrôleur de navigation.
Steve Moser
2

SWIFT 4 :

1. Créez une @IBAction avec enchaînement à l'intérieur du contrôleur que vous souhaitez vous détendre:

    @IBAction func unwindToVC(segue: UIStoryboardSegue) {

    }

2. Dans le storyboard, à partir du contrôleur que vous souhaitez séparer (dérouler) de ctrl + faire glisser du signe du contrôleur vers le signe de sortie et choisissez la méthode que vous avez créée précédemment:

entrez la description de l'image ici

3. Vous pouvez maintenant remarquer que dans le plan du document, vous avez une nouvelle ligne avec le titre "Se dérouler segue ....". Maintenant, vous devez cliquer sur cette ligne et ouvrir l'inspecteur d'attributs pour définir l'identifiant (dans mon cas, unwindSegueIdentifier ).

entrez la description de l'image ici

4. Vous avez presque terminé! Maintenant, vous devez ouvrir le contrôleur de vue dont vous souhaitez vous détendre et créer une méthode qui effectuera la séquence. Par exemple, vous pouvez ajouter un bouton, le connecter avec du code avec @IBAction , après cela, à l'intérieur de cette IBAction, ajoutez la méthode perfromSegue (withIdentifier: sender :) :

     @IBAction func unwindToSomeVCWithSegue(_ sender: UIButton) {
         performSegue(withIdentifier: "unwindSegueIdentifier", sender: nil)
     }

C'est tout ce que vous avez à faire!

wm.p1us
la source
Est-il possible de créer la connexion "exit" dans le contrôleur de vue source par programmation?
Andrew Kirna
1

Swift 4.2, Xcode 10+

Pour ceux qui se demandent comment faire cela avec des VC non configurés via le storyboard (ceux qui viennent à cette question en recherchant "par programmation" + "se détendre segue").

Étant donné que vous ne pouvez pas configurer une séquence de déroulement par programme, la solution uniquement programmatique la plus simple consiste à appeler:

navigationController?.popToRootViewController(animated: true)

qui fera revenir tous les contrôleurs de vue de la pile vers votre contrôleur de vue racine.


Pour faire apparaître uniquement le contrôleur de vue le plus haut de la pile de navigation, utilisez:

navigationController?.popViewController(animated: true)

10623169
la source
1
c'est généralement plus que ce que vous voulez - pour en faire ressortir une, faites simplement: [self.navigationController popViewControllerAnimated: YES];
Andy Weinstein
En effet, j'ai ajouté cela à ma réponse - merci @AndyWeinstein
10623169
0

FYI: Pour que la réponse de @ Vadim fonctionne avec une action de déroulement manuel appelée à partir d'un View Controller, vous devez placer la commande:

[self performSegueWithIdentifier:(NSString*) identifier sender:(id) sender];

à l'intérieur de la méthode de classe surchargée viewDidAppear comme ceci:

-(void) viewDidAppear:(BOOL) animated
{
    [super viewDidAppear: animated];

    [self performSegueWithIdentifier:@"SomeSegueIdentifier" sender:self];
}

Si vous le placez dans d'autres méthodes ViewController comme viewDidLoad ou viewWillAppear, il sera ignoré.

John Verco
la source
3
Certainement faux. Appelez performSegueWithIdentifier où vous voulez.
smileBot
Cela ne ferait-il pas juste une séquence de déroulement dès que la vue se chargerait? Plutôt que de jouer quand VOUS le souhaitez, par exemple après avoir appuyé sur un bouton.
Pahnev
@Pahnev oui, ce serait le cas. Je ne sais pas comment cette réponse a obtenu des votes positifs. AppelperformSegueWithIdentfier fait exactement cela: effectuer la transition d'un ViewController à un autre
ezcoding
Totalement faux. Il serait juste de rembobiner immédiatement au lancement.
Lee Probert