Comment passer prepareForSegue: un objet

j'ai beaucoup d'annotations dans un mapview (avec les boutons rightCalloutAccessory ). Le bouton va effectuer une transition de ce mapview à un tableview . Je veux passer le tableview un objet différent (qui contient des données) en fonction du bouton callout qui a été cliqué.

par exemple: (entièrement confectionné)

  • annotation1 (Austin) -> col de données obj 1 (Austin)
  • annotation2 (Dallas) - > données sur les laissez-passer obj 2 (Dallas)
  • annotation3 (Houston) -> col de données obj 3 et ainsi de suite... (vous avez l' idea)

je suis capable de détecter le bouton d'appel qui a été cliqué.

j'utilise prepareForSegue : pour passer les données obj à la destination ViewController . Puisque je ne peux pas faire cet appel prendre un argument supplémentaire pour les données obj j'ai besoin, quels sont quelques moyens élégants pour atteindre le même effet (données obj dynamique)?

N'importe quel conseil serait apprécié.

343
demandé sur Grender 2011-10-23 08:34:43

10 réponses

saisissez simplement une référence au contrôleur de vue cible dans la méthode prepareForSegue: et passez tous les objets dont vous avez besoin. Voici un exemple...

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    // Make sure your segue name in storyboard is the same as this line
    if ([[segue identifier] isEqualToString:@"YOUR_SEGUE_NAME_HERE"])
    {
        // Get reference to the destination view controller
        YourViewController *vc = [segue destinationViewController];

        // Pass any objects to the view controller here, like...
        [vc setMyObjectHere:object];
    }
}
Révision

: vous pouvez également utiliser la méthode performSegueWithIdentifier:sender: pour activer la transition vers une nouvelle vue basée sur une sélection ou une pression sur un bouton.

par exemple, considérer que j'avais deux contrôleurs de vue. Le premier contient trois boutons et le second doit savoir lequel de ces boutons a été pressée avant la transition. Vous pouvez brancher les boutons jusqu'à un IBAction dans votre code qui utilise la méthode performSegueWithIdentifier: , comme ceci...

// When any of my buttons are pressed, push the next view
- (IBAction)buttonPressed:(id)sender
{
    [self performSegueWithIdentifier:@"MySegue" sender:sender];
}

// This will get called too before the view appears
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"MySegue"]) {

        // Get destination view
        SecondView *vc = [segue destinationViewController];

        // Get button tag number (or do whatever you need to do here, based on your object
        NSInteger tagIndex = [(UIButton *)sender tag];

        // Pass the information to your destination view
        [vc setSelectedButton:tagIndex];
    }
}

EDIT: L'application de démonstration que j'ai à l'origine joint a maintenant six ans, donc je l'ai enlevé pour éviter toute confusion.

664
répondu Simon 2017-08-02 09:13:33

la réponse acceptée n'est pas la meilleure façon de le faire, car elle crée une dépendance inutile entre deux contrôleurs de vue. Voici comment vous pouvez le faire sans vous soucier du type de contrôleur de vue de destination:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.destinationViewController respondsToSelector:@selector(setMyData:)]) {
        [segue.destinationViewController performSelector:@selector(setMyData:) 
                                              withObject:myData];
    } 
}

aussi longtemps que votre contrôleur de vue de destination déclare un bien public, par exemple:

@property (nonatomic, strong) MyData *myData;

vous pouvez définir cette propriété dans le contrôleur de vue précédent comme je l'ai décrit ci-dessus.

81
répondu Macondo2Seattle 2014-07-01 23:38:46

dans Swift je ferais quelque chose comme ça:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let yourVC = segue.destinationViewController as? YourViewController {
        yourVC.yourData = self.someData
    }
}
19
répondu Remy Cilia 2017-02-22 16:13:29

j'ai un "151940920 expéditeur" classe , comme cette

@class MyEntry;

@interface MySenderEntry : NSObject
@property (strong, nonatomic) MyEntry *entry;
@end

@implementation MySenderEntry
@end

j'utilise ce "151940920 expéditeur" classe pour le passage des objets à prepareForSeque:sender:

-(void)didSelectItemAtIndexPath:(NSIndexPath*)indexPath
{
    MySenderEntry *sender = [MySenderEntry new];
    sender.entry = [_entries objectAtIndex:indexPath.row];
    [self performSegueWithIdentifier:SEGUE_IDENTIFIER_SHOW_ENTRY sender:sender];
}

-(void)prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:SEGUE_IDENTIFIER_SHOW_ENTRY]) {
        NSAssert([sender isKindOfClass:[MySenderEntry class]], @"MySenderEntry");
        MySenderEntry *senderEntry = (MySenderEntry*)sender;
        MyEntry *entry = senderEntry.entry;
        NSParameterAssert(entry);

        [segue destinationViewController].delegate = self;
        [segue destinationViewController].entry = entry;
        return;
    }

    if ([[segue identifier] isEqualToString:SEGUE_IDENTIFIER_HISTORY]) {
        // ...
        return;
    }

    if ([[segue identifier] isEqualToString:SEGUE_IDENTIFIER_FAVORITE]) {
        // ...
        return;
    }
}
16
répondu neoneye 2012-12-08 14:02:07

j'ai rencontré cette question quand j'essayais d'apprendre comment passer des données d'un contrôleur de vue à un autre. J'ai besoin de quelque chose de visuel pour m'aider à apprendre, donc cette réponse est un supplément aux autres déjà ici. Elle est un peu plus générale que la question initiale, mais elle peut être adaptée au travail.

cet exemple de base fonctionne comme ceci:

enter image description here

l'idée est de passer une chaîne du champ texte dans le Controller de la première vue au label dans le Controller de la deuxième vue.

Premier-Vue-Contrôleur

import UIKit

class FirstViewController: UIViewController {

    @IBOutlet weak var textField: UITextField!

    // This function is called before the segue
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

        // get a reference to the second view controller
        let secondViewController = segue.destinationViewController as! SecondViewController

        // set a variable in the second view controller with the String to pass
        secondViewController.receivedString = textField.text!
    }

}

Seconde Vue-Contrôleur

import UIKit

class SecondViewController: UIViewController {

    @IBOutlet weak var label: UILabel!

    // This variable will hold the data being passed from the First View Controller
    var receivedString = ""

    override func viewDidLoad() {
        super.viewDidLoad()

        // Used the text from the First View Controller to set the label
        label.text = receivedString
    }

}

Rappelez-vous

  • faire la séquence par control en cliquant sur le bouton et en le drainant vers le contrôleur de la deuxième vue.
  • le raccordement de la les prises pour le UITextField et le UILabel .
  • définit les contrôleurs first et second View aux fichiers Swift appropriés dans IB.

Source

Comment envoyer des données à travers des enchaînements (swift) (YouTube tutoriel)

Voir aussi

Afficher les Contrôleurs: la transmission des données vers l'avant et la transmission des données en arrière (fuller répondre)

11
répondu Suragch 2017-05-23 12:02:46

j'ai implémenté une bibliothèque avec une catégorie sur UIViewController qui simplifie cette opération. Fondamentalement, vous définissez les paramètres que vous voulez passer dans un Nsdiction associé à L'item UI qui exécute la séquence. Il fonctionne aussi avec des séquences manuelles.

par exemple, vous pouvez faire

[self performSegueWithIdentifier:@"yourIdentifier" parameters:@{@"customParam1":customValue1, @"customValue2":customValue2}];

pour une séquence manuelle ou créer un bouton avec une séquence et utiliser

[button setSegueParameters:@{@"customParam1":customValue1, @"customValue2":customValue2}];

si contrôleur de vue de destination n'est pas valeur-clé de codage conforme pour une clé, rien ne se passe. Il fonctionne avec des valeurs-clés aussi (utile pour décompresser des segments). Découvrez-le ici https://github.com/stefanomondino/SMQuickSegue

4
répondu Stefano Mondino 2014-02-21 11:26:30

pour Swift utilisez ceci,

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    var segueID = segue.identifier

    if(segueID! == "yourSegueName"){

        var yourVC:YourViewController = segue.destinationViewController as YourViewController

        yourVC.objectOnYourVC = setObjectValueHere!

    }
}
4
répondu Zaid Pathan 2015-03-27 11:53:10

ma solution est similaire.

// In destination class: 
var AddressString:String = String()

// In segue:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
   if (segue.identifier == "seguetobiddetailpagefromleadbidder")
    {
        let secondViewController = segue.destinationViewController as! BidDetailPage
        secondViewController.AddressString = pr.address as String
    }
}
2
répondu A.G 2016-01-25 17:14:28

j'ai utilisé cette solution pour garder l'invocation de la séquence et la communication de données dans la même fonction:

private var segueCompletion : ((UIStoryboardSegue, Any?) -> Void)?

func performSegue(withIdentifier identifier: String, sender: Any?, completion: @escaping (UIStoryboardSegue, Any?) -> Void) {
    self.segueCompletion = completion;
    self.performSegue(withIdentifier: identifier, sender: sender);
    self.segueCompletion = nil
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    self.segueCompletion?(segue, sender)
}

Un cas d'utilisation serait quelque chose comme:

func showData(id : Int){
    someService.loadSomeData(id: id) {
        data in
        self.performSegue(withIdentifier: "showData", sender: self) {
            storyboard, sender in
            let dataView = storyboard.destination as! DataView
            dataView.data = data
        }
    }
}

cela semble fonctionner pour moi, cependant, je ne suis pas sûr à 100% que les fonctions perform et prepare sont toujours exécutées sur le même thread.

0
répondu dannrob 2016-11-22 03:23:15

il suffit d'utiliser cette fonction.

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let index = CategorytableView.indexPathForSelectedRow
    let indexNumber = index?.row
    let VC = segue.destination as! DestinationViewController
   VC.value = self.data

}
0
répondu Parth Barot 2018-04-12 12:40:05