tutorial manager example corelocation ios xcode uitableview mapkit storyboard

ios - manager - Cómo pasar prepareForSegue: un objeto



location manager swift tutorial (10)

Tengo muchas anotaciones en una vista de rightCalloutAccessory (con los botones de rightCalloutAccessory ). El botón ejecutará un segmento de esta vista de tableview a una vista de tableview . Quiero pasar la vista de tableview un objeto diferente (que contiene datos) dependiendo de qué botón de llamada se hizo clic.

Por ejemplo: (totalmente confeccionado)

  • anotación1 (Austin) -> pasar datos obj 1 (relevante para Austin)
  • anotación2 (Dallas) -> pasar datos obj 2 (relevante a Dallas)
  • anotación3 (Houston) -> pasar datos obj 3 y así sucesivamente ... (se entiende la idea)

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

Estoy usando prepareForSegue : para pasar el objeto de datos al ViewController destino. Ya que no puedo hacer que esta llamada tome un argumento adicional para el objeto de datos que necesito, ¿cuáles son algunas formas elegantes de lograr el mismo efecto (objeto dinámico de datos)?

Cualquier consejo sería apreciado.


En Swift yo haría algo así:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if let yourVC = segue.destinationViewController as? YourViewController { yourVC.yourData = self.someData } }


He implementado una biblioteca 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 la interfaz de usuario que está realizando el segue. Funciona con segues manuales también.

Por ejemplo, puedes hacer

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

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

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

Si el controlador de vista de destino no es compatible con la codificación de valor-clave para una clave, no sucede nada. También funciona con valores-clave (útil para desenrollar segues). Compruébelo aquí https://github.com/stefanomondino/SMQuickSegue


La respuesta aceptada no es la mejor forma de hacerlo, porque crea una dependencia innecesaria en tiempo de compilación entre dos controladores de vista. Aquí le mostramos cómo 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]; } }

Entonces, siempre que 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.


Me encontré con esta pregunta cuando estaba tratando de aprender cómo pasar los 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 complemento a los otros que ya están aquí. Es un poco más general que la pregunta original, pero puede adaptarse al trabajo.

Este ejemplo básico funciona así:

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.

Primer controlador 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 la 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

  • Haga la secuencia presionando el control haciendo clic en el botón y pasándolo al Second View Controller.
  • UITextField los puntos de venta de la UITextField y la UILabel .
  • Establezca el primer y segundo Controladores de vista en los archivos Swift correspondientes en IB.

Fuente

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

Ver también

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


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


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


Sólo tiene que utilizar 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 }


Simplemente tome una referencia al controlador de vista de destino en el método prepareForSegue: y pase todos los objetos 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]; } }

REVISIÓN: También puede usar el performSegueWithIdentifier:sender: para activar la transición a una nueva vista basada en una selección o presionando un 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 presionó antes de la transición. Puede conectar los botones a una IBAction en su código que utilice el método performSegueWithIdentifier: así ...

// 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, por lo que la he eliminado para evitar confusiones.


Tengo una clase de remitente , como esta

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

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


Utilicé esta solución para poder mantener la invocación del segmento 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 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 siempre se ejecuten en el mismo hilo.