Cómo pasar prepareForSegue: un objeto


Tengo muchas anotaciones en una vista de mapa (con botones rightCalloutAccessory). El botón realizará una transición de este mapview a un tableview. Quiero pasar al tableview un objeto diferente (que contiene datos) dependiendo de qué botón de llamada se hizo clic.

Por ejemplo: (totalmente hecho)

  • anotación1 (Austin) - > datos de pase obj 1 (relevante para Austin)
  • annotation2 (Dallas) - > pass data obj 2 (relevant to Dallas)
  • anotación3 (Houston) -> pasar datos obj 3 y así sucesivamente... (usted consigue el idea)

Soy capaz de detectar qué botón de llamada se hizo clic.

Estoy usando prepareForSegue: para pasar el obj de datos al destino ViewController. Dado que no puedo hacer esta llamada tomar un argumento adicional para el obj de datos que requiero, ¿cuáles son algunas formas elegantes de lograr el mismo efecto (obj de datos dinámicos)?

Cualquier consejo sería apreciado.

Author: Grender, 2011-10-23

10 answers

Simplemente tome una referencia al controlador de vista de destino en el método prepareForSegue: y pase los objetos que necesite allí. He aquí un ejemplo...

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

REVISIÓN: También puede usar el método performSegueWithIdentifier:sender: para activar la transición a una nueva vista basada en una selección o pulsación de botón.

Por ejemplo, considere que tenía dos controladores de vista. El primero contiene tres botones y el segundo necesita saber cuál de esos botones se ha presionado antes de la transición. Podrías conectar los botones a un IBAction en su código que usa el método performSegueWithIdentifier:, como este...

// 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];
    }
}

EDITAR: La aplicación de demostración que adjunté originalmente tiene ahora seis años, así que la he eliminado para evitar cualquier confusión.

 664
Author: Simon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-02 09:13:33

La respuesta aceptada no es la mejor manera de hacer esto, porque crea una dependencia innecesaria en tiempo de compilación entre dos controladores de vista. Así es como puede hacerlo sin preocuparse por el tipo de controlador de vista de destino:

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

Así que siempre y cuando su controlador de vista de destino declare una propiedad pública, por ejemplo:

@property (nonatomic, strong) MyData *myData;

Puede establecer esta propiedad en el controlador de vista anterior como describí anteriormente.

 81
Author: Macondo2Seattle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-01 23:38:46

En Swift haría algo así:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let yourVC = segue.destinationViewController as? YourViewController {
        yourVC.yourData = self.someData
    }
}
 19
Author: Remy Cilia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-22 16:13:29

Tengo una clase de remitente , como esta

@class MyEntry;

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

@implementation MySenderEntry
@end

Uso esta clase de remitente para pasar objetos a 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
Author: neoneye,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-08 14:02:07

Me encontré con esta pregunta cuando estaba tratando de aprender cómo pasar datos de un Controlador de vista a otro. Sin embargo, necesito algo visual que me ayude a aprender, por lo que esta respuesta es un suplemento a las otras que ya están aquí. Es un poco más general que la pregunta original, pero se puede adaptar para funcionar.

Este ejemplo básico funciona así:

introduzca la descripción de la imagen aquí

La idea es pasar una cadena desde el campo de texto en el Primer Controlador de Vista a la etiqueta en el Segundo Controlador de Vista.

Controlador de Primera vista

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!
    }

}

Controlador de segunda vista

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
    }

}

Recuerda{[16]]}
  • Haga el segue control haciendo clic en el botón y arrastrándolo al Segundo Controlador de Vista.
  • Conecta las salidas para el UITextField y el UILabel.
  • Establezca el primer y segundo View Controllers en los archivos Swift apropiados en IB.

Fuente

Cómo enviar datos a través de segue (swift) (Tutorial de YouTube)

Véase también

Controladores de vista: Pasar datos hacia adelante y pasar datos hacia atrás (respuesta más completa)

 11
Author: Suragch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:46

He implementado una librería con una categoría en UIViewController que simplifica esta operación. Básicamente, establece los parámetros que desea pasar en un NSDictionary asociado al elemento de interfaz de usuario que realiza el segue. También funciona con secuencias manuales.

Por ejemplo, puede hacer

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

Para un segue manual o cree un botón con un segue y use

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

Si el controlador de vista de destino no cumple con la codificación clave-valor para una clave, no sucede nada. Funciona con valores clave también (útil para desenrollar segues). Échale un vistazo aquí https://github.com/stefanomondino/SMQuickSegue

 4
Author: Stefano Mondino,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-21 11:26:30

Para Swift use esto,

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
Author: Zaid Pathan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-27 11:53:10

Mi solución es similar.

// 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
Author: A.G,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-25 17:14:28

Utilicé esta solución para poder mantener la invocación del segue y la comunicación de datos dentro de la misma función:

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 caso de uso sería algo así como:

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

Esto parece funcionar para mí, sin embargo, no estoy 100% seguro de que las funciones perform y prepare siempre se ejecuten en el mismo hilo.

 0
Author: dannrob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-22 03:23:15

Simplemente use esta función.

 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
Author: Parth Barot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-12 12:40:05