Acceda al controlador de vista de contenedor desde el padre iOS

en iOS6 noté la nueva Vista de contenedor, pero no estoy muy seguro de cómo acceder a su controlador desde la vista que contiene.

Guión:

ejemplo

Quiero acceder a las tags en el controlador de vista Alerta desde el controlador de vista que aloja la vista de contenedor.

Hay una transición entre ellos, ¿puedo usar eso?

Sí, puede usar la transición para obtener acceso al controlador de vista hijo (y su vista y sus subvistas). Proporcione a segue un identificador (como alertview_embed ), utilizando el inspector de atributos en Storyboard. Luego, haga que el controlador de vista principal (el que alberga la vista de contenedor) implemente un método como este:

 - (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { NSString * segueName = segue.identifier; if ([segueName isEqualToString: @"alertview_embed"]) { AlertViewController * childViewController = (AlertViewController *) [segue destinationViewController]; AlertView * alertView = childViewController.view; // do something with the AlertView's subviews here... } } 

Puede hacerlo simplemente con self.childViewControllers.lastObject (suponiendo que solo tenga un hijo, de lo contrario use objectAtIndex: .

para la progtwigción Swift

puedes escribir así

 var containerViewController: ExampleViewController? override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { // you can set this name in 'segue.embed' in storyboard if segue.identifier == "checkinPopupIdentifierInStoryBoard" { let connectContainerViewController = segue.destinationViewController as ExampleViewController containerViewController = connectContainerViewController } } 

El método prepareForSegue funciona, pero depende de la cadena mágica del identificador de segue. Tal vez hay una mejor manera.

Si conoce la clase del VC que está buscando, puede hacerlo muy bien con una propiedad calculada:

 var camperVan: CamperVanViewController? { return childViewControllers.flatMap({ $0 as? CamperVanViewController }).first // This works because `flatMap` removes nils } 

Esto depende de childViewControllers . Aunque estoy de acuerdo en que podría ser frágil confiar en el primero, nombrar la clase que buscas hace que parezca bastante sólido.

Una respuesta actualizada para Swift 3, utilizando una propiedad calculada:

 var jobSummaryViewController: JobSummaryViewController { get { let ctrl = childViewControllers.first(where: { $0 is JobSummaryViewController }) return ctrl as! JobSummaryViewController } } 

Esto solo itera la lista de niños hasta que alcanza la primera coincidencia.

self.childViewControllers es más relevante cuando necesitas el control del padre. Por ejemplo, si el controlador secundario es una vista de tabla y desea recargarlo con fuerza o cambiar una propiedad mediante un toque de botón o cualquier otro evento en el Controlador de vista principal, puede hacerlo accediendo a la instancia de ChildViewController y no a través de prepareForSegue. Ambos tienen sus aplicaciones de diferentes maneras.

Uso el código como:

 - (IBAction)showCartItems:(id)sender{ ListOfCartItemsViewController *listOfItemsVC=[self.storyboard instantiateViewControllerWithIdentifier:@"ListOfCartItemsViewController"]; [self addChildViewController:listOfItemsVC]; } 

En caso de que alguien esté buscando Swift 3.0 ,

viewController1 , viewController2 , etc., estarán accesibles.

 let viewController1 : OneViewController! let viewController2 : TwoViewController! // Safety handling of optional String if let identifier: String = segue.identifier { switch identifier { case "segueName1": viewController1 = segue.destination as! OneViewController break case "segueName2": viewController2 = segue.destination as! TwoViewController break // ... More cases can be inserted here ... default: // A new segue is added in the storyboard but not yet including in this switch print("A case missing for segue identifier: \(identifier)") break } } else { // Either the segue or the identifier is inaccessible print("WARNING: identifier in segue is not accessible") } 

Hay otra manera de usar la statement de cambio de Swift en el tipo de controlador de vista:

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { switch segue.destination { case let aViewController as AViewController: self.aViewController = aViewController case let bViewController as BViewController: self.bViewController = bViewController default: return } } 

puedes escribir así

 - (IBAction)showDetail:(UIButton *)sender { DetailViewController *detailVc = [self.childViewControllers firstObject]; detailVc.lable.text = sender.titleLabel.text; } } 

Con genérico puede hacer algunas cosas dulces. Aquí hay una extensión de Array:

 extension Array { func firstMatchingType() -> Type? { return first(where: { $0 is Type }) as? Type } } 

A continuación, puede hacer esto en su viewController:

 var viewControllerInContainer: YourViewControllerClass? { return childViewControllers.firstMatchingType()! } 
    Intereting Posts