Cómo pasar prepareForSegue: un object

Tengo muchas annotations en una vista de rightCalloutAccessory (con los botones rightCalloutAccessory ). El button realizará una segue desde esta vista de tableview a una vista de tableview . Quiero pasar la vista de tableview un object diferente (que contiene datos) dependiendo de qué button de llamada se hizo clic.

Por ejemplo: (totalmente inventado)

  • annotation1 (Austin) -> pass data obj 1 (relevante para Austin)
  • annotation2 (Dallas) -> pass data obj 2 (relevante para Dallas)
  • anotación3 (Houston) -> datos de paso obj 3 y demás … (obtienes la idea)

Soy capaz de detectar qué button de llamada se hizo clic.

Estoy usando prepareForSegue : para pasar el obj de datos al ViewController destino. Dado que no puedo hacer que esta llamada tome un argumento adicional para los datos obj que necesito, ¿cuáles son algunas forms elegantes de lograr el mismo efecto (datos dynamics obj)?

Cualquier sugerencia sería apreciada.

Simplemente tome una reference al controller de vista de destino en prepareForSegue: método y pase cualquier object que necesite allí. Aquí hay 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]; } } 

REVISION: También puede usar performSegueWithIdentifier:sender: método para activar la transición a una nueva vista basada en una selección o presionar un button.

Por ejemplo, considere que tenía dos controlleres de vista. El primero contiene tres botones y el segundo necesita saber qué botones se han presionado antes de la transición. Puede cablear los botones hasta una IBAction en su código que utiliza performSegueWithIdentifier: method, like this …

 // 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 originalmente adjunté ahora tiene seis años, por lo que la eliminé para evitar confusiones.

La respuesta aceptada no es la mejor manera de hacer esto, ya que crea una dependencia de time de compilation innecesaria entre dos controlleres de vista. A continuación, le indicamos cómo puede hacerlo sin preocuparse por el tipo de controller de vista de destino:

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

Entonces, mientras su controller de vista de destino declare una propiedad pública, por ejemplo:

 @property (nonatomic, strong) MyData *myData; 

puede configurar esta propiedad en el controller de vista anterior como describí anteriormente.

Tengo una class de remitente , como esta

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

Utilizo esta class de remitente para pasar objects para 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; } } 

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

Encontré esta pregunta cuando intentaba aprender cómo pasar datos de un controller de visualización a otro. Necesito algo visual para ayudarme a aprender, así que esta respuesta es un suplemento a los otros que ya están aquí. Es un poco más general que la pregunta original pero puede adaptarse 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 text en el primer controller de vista a la label en el segundo controller de vista.

Primer controller de 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 } } 

Restring

  • Haga clic en el control haciendo clic en el button y arrastrándolo hacia el segundo controller de vista.
  • UITextField los puntos de venta para UITextField y UILabel .
  • Establezca el primer y segundo View Controllers en los files Swift apropiados en IB.

Fuente

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

Ver también

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

Implementé una biblioteca con una categoría en UIViewController que simplifica esta operación. Básicamente, establece los parameters que desea pasar en un NSDictionary asociado al elemento de interfaz de usuario que está realizando la segue. También funciona con segues manuales.

Por ejemplo, puede hacer

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

para un segue manual o cree un button con un segue y use

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

Si el controller de vista de destino no es compatible con la encoding de valores key para una key, no sucede nada. Funciona también con valores-key (útil para desenrollar segues). Compruébelo aquí https://github.com/stefanomondino/SMQuickSegue

Para Swift usa 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! } } 

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

Utilicé esta solución para que pudiera mantener la invocación del Segue y la comunicación de datos dentro de la misma function:

 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 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 de realizar y preparar se ejecuten siempre en el mismo hilo.