¿Cómo realizar Unwind segue programáticamente?

307

Usar el guión gráfico es muy fácil. Simplemente arrastre la acción a "Salir". Pero, ¿cómo debo llamarlo desde mi código?

tadasz
fuente
33
Me parece una pregunta válida, la tuve yo mismo. Puede realizar una secuencia de desenrollado mediante programación 1. creando una secuencia manual (ctrl-arrastre desde el Propietario del archivo para salir), 2. dándole un nombre en IB, luego 3. haciendo un normal -performSegueWithIdentifier: remitente: en su código.
Yang Meyer
66
No debería haber sido cerrado IMO. Los usuarios que votaron para cerrar esta pregunta seguramente no parecen tener un fondo Obj-C / Cocoa Touch.
LJ Wilson
Yang: ¿Cómo le das un nombre?
sarfata
Acabo de usar [self despedsViewControllerAnimated: YES complete: nil]; para salir programáticamente. No sé si es una forma correcta o no.
tangqiaoboy
1
sarfata: Primero crea un "desenrollado manual segue" presionando ctrl-drag desde viewcontroller a "Exit". Luego puede encontrar la secuencia en el Esquema del documento.
Huggie

Respuestas:

283
  1. Cree un segue manual ( ctrl-drag del propietario del archivo para salir),
  2. Elíjalo en el menú del controlador izquierdo debajo del botón verde EXIT.

Elíjalo en el menú del controlador izquierdo debajo del botón verde EXIT

Inserte el nombre de Segue para relajarse.

Luego, - (void)performSegueWithIdentifier:(NSString *)identifier sender:(id)sender.con su segue identificarse.

Vadim
fuente
25
1) "Propietario del archivo": ¿no es esa terminología antigua? Me funcionó para controlar el arrastre del controlador de vista a su ícono Salir. 2) Aunque debería ser obvio, Xcode está buscando una declaración en la interfaz de la IBAction que tome un argumento UIStoryboardSegue; la charla de la sesión 407 de WWDC 2012 no mencionó eso y no pegó ese código. Sin él, mi ícono de Salir no se activaría al arrastrar el control hacia él. 3) ¡Es genial que al final de tu gran flecha roja, en el campo Acción, puedas presionar la flecha "ir allí"!
tobinjim
71
Para cualquiera que, como yo, todavía tenga problemas para implementar esta respuesta, preparé un tutorial y un ejemplo más exhaustivo en este repositorio: github.com/bradley/iOSUnwindSegueProgramatic (Sin intentar publicitarme, me golpeé la cabeza contra la pared durante horas en esto y ver una configuración de trabajo me ayuda.)
bradleygriffith
3
@bradleygriffith Eres increíblemente increíble. ¡Gracias por el gran tutorial!
Eli_Rozen
77
@bradleygriffith ¡Desearía que hubieras respondido esto para que yo también pudiera marcar eso! Su contribución única fue establecer qué controlador de vista obtiene qué código . No pude encontrar eso en ningún lado. ¡Gracias!
Aaron Vegh
3
La clave, para cualquiera que todavía esté perplejo con esto, es que la IBACTION debe estar en el controlador de vista al que está volviendo, no en el que está actualmente. @Bradleygriffith explica esto en GitHub, pero no lo he visto mencionado en otro lugar. Esa parte es crítica.
Axeva
163

Aquí hay una respuesta completa con el objetivo C y Swift:

1) Cree un IBActionsegmento de desconexión en su controlador de vista de destino (donde desea realizar el seguimiento). En cualquier lugar del archivo de implementación.

// Objective C

    - (IBAction)unwindToContainerVC:(UIStoryboardSegue *)segue {

    }

// Swift

 @IBAction func unwindToContainerVC(segue: UIStoryboardSegue) {

    }

2) En el controlador de vista de origen (el controlador del que está segue), ⌃ + arrastre desde "Nombre de la actividad" para salir. Debería ver la secuencia de desenrollado creada en el paso 1 en la ventana emergente. (Si no lo ve, revise el primer paso). Elija unwindToContainerVC: de la ventana emergente, o lo que sea que haya denominado su método para conectar su controlador de origen a la función IBAction de desenrollar.

ingrese la descripción de la imagen aquí

3) Seleccione el segue en el esquema del documento del controlador de vista de origen del guión gráfico (aparecerá en la lista al final) y dele un identificador .

ingrese la descripción de la imagen aquí

4) Llame al desenrollar segue usando este método desde el controlador de vista de origen , sustituyendo su nombre de desenrollar segue.

// C objetivo

[self performSegueWithIdentifier:@"unwindToContainerVC" sender:self];

// Swift

self.performSegueWithIdentifier("unwindToContainerVC", sender: self)

NÓTESE BIEN. Use la propiedad sourceViewController del parámetro segue en el método de desenrollado para acceder a las propiedades expuestas en el controlador de origen. Además, observe que el marco se encarga de descartar el controlador de origen. Si desea confirmar esto, agregue un método dealloc al controlador de origen con un mensaje de registro que debería activarse una vez que se haya eliminado. Si Dealloc no dispara, es posible que tenga un ciclo de retención.

smileBot
fuente
2
Mi programa no funciona, ni siquiera se llama(IBAction)unwindToContainerVC:(UIStoryboardSegue *)segue
xhg
2
esta solución no funciona cuando el controlador de vista, al que se está desenrollando, solo existe en su guión gráfico, es decir, no tiene una implementación personalizada de código
mnl
@mnl no estoy seguro exactamente de lo que estás diciendo, pero funciona con escenas o plumillas de guiones gráficos. Si está creando una escena del controlador de vista en el código, entonces no usaría ningún método que "devuelva" IB en su nombre, lo cual es realmente nulo de todos modos, ya que sirven para comunicarse entre el código y el IB. ¿Eso aborda tu comentario?
smileBot
1
Su imagen mostrando el ctrl+dragdesde ViewControllerhasta Exitfue increíblemente útil. ¡Gracias!
kbpontius
Para Swift 4.2 use: self.performSegue (withIdentifier: "unwindToVC", remitente: self)
Reefwing
81

bradleygriffithLa respuesta fue genial. Tomé el paso 10 e hice una captura de pantalla para simplificar. Esta es una captura de pantalla en Xcode 6.

  1. Control-arrastre desde el ícono naranja hasta el ícono rojo Salir para crear un desenrollado sin ninguna acción / botón en la vista.

ingrese la descripción de la imagen aquí

  1. Luego seleccione el unwind segueen la barra lateral:

ingrese la descripción de la imagen aquí

  1. Establecer una cadena de identificador de Segue:

ingrese la descripción de la imagen aquí

  1. Acceda a ese identificador desde el código:
[self performSegueWithIdentifier:@"unwindIdentifier" sender:self];
Decano
fuente
44
En primer lugar, el método para desenrollar debe incluirse dentro de UIViewController. Entonces su solución funcionará
Alex Cio
55
¡y tienes que establecer el Identificador en este nuevo segmento! No te olvides de eso.
kraag22
1
¿Es posible crear la conexión de "salida" en el controlador de vista de origen mediante programación?
Andrew Kirna
13

Utilicé lo [self dismissViewControllerAnimated: YES completion: nil];que te devolverá a la llamada ViewController.

Larry Gibson
fuente
66
Larry, ese es un enfoque perfectamente válido si quieres volver al controlador de vista anterior, es decir, el que presentó el que estás saliendo ahora. La pregunta surgió porque lo nuevo en Xcode 4.5 es la capacidad de "relajarse" de un controlador de vista en algún lugar del orden de presentación a un controlador de vista mucho anterior. Vea la sesión 407 de WWDC 2012 para más detalles.
tobinjim
11

Citando texto de la Nota técnica de Apple sobre Unwind Segue: para agregar un desenlace de desenrollado que solo se activará mediante programación, controle + arrastre desde el ícono del controlador de vista de la escena hasta su ícono de salida, luego seleccione una acción de desenrollar para el nuevo segue del menú emergente.

Enlace a la nota técnica

Vishal Chaudhry
fuente
6

La respuesta de Vishal Chaudhry anterior funcionó para mí. También agregaría eso para activar manualmente la secuencia usando:

[self performSegueWithIdentifier:@"mySegueName" sender:self];

desde ViewController también debe seleccionar el desenrollar segue en la escena de ViewController en el guión gráfico y en la vista de propiedades en el RHS asegúrese de que el campo Identificador contenga el nombre al que se refiere en el código ("mySegueName" en el ejemplo anterior )

Si omite este paso, la línea anterior arrojará una excepción de que no se conoce el nombre de la secuencia.

Jason Crocker
fuente
3

Solución compatible con versiones anteriores que funcionará para versiones anteriores a ios6, para aquellos interesados:

- (void)unwindToViewControllerOfClass:(Class)vcClass animated:(BOOL)animated {

    for (int i=self.navigationController.viewControllers.count - 1; i >= 0; i--) {
        UIViewController *vc = [self.navigationController.viewControllers objectAtIndex:i];
        if ([vc isKindOfClass:vcClass]) {
            [self.navigationController popToViewController:vc animated:animated];
            return;
        }
    }
}
Joel Teply
fuente
2
Los segmentos de desconexión hacen mucho más que regresar a una determinada clase en una pila de controlador de navegación.
Steve Moser
2

SWIFT 4 :

1. Cree una @IBAction con segue dentro del controlador que desea desenrollar:

    @IBAction func unwindToVC(segue: UIStoryboardSegue) {

    }

2. En el guión gráfico, desde el controlador que desea segue (desenrollar) de ctrl + arrastre desde el signo del controlador para salir del signo y elegir el método que creó anteriormente:

ingrese la descripción de la imagen aquí

3. Ahora puede notar que en el esquema del documento tiene una nueva línea con el título "Desenrollar segue ....". Ahora debe hacer clic en esta línea y abrir el inspector de atributos para establecer el identificador (en mi caso, unwindSegueIdentifier ).

ingrese la descripción de la imagen aquí

4. ¡Ya casi has terminado! Ahora debe abrir el controlador de vista del que desea desconectarse y crear algún método que realice segue. Por ejemplo, puede agregar un botón, conectarlo con el código con @IBAction , después de eso, dentro de este IBAction, agregue el método perfromSegue (withIdentifier: sender :) :

     @IBAction func unwindToSomeVCWithSegue(_ sender: UIButton) {
         performSegue(withIdentifier: "unwindSegueIdentifier", sender: nil)
     }

¡Entonces eso es todo lo que tienes que hacer!

wm.p1us
fuente
¿Es posible crear la conexión de "salida" en el controlador de vista de origen mediante programación?
Andrew Kirna
1

Swift 4.2, Xcode 10+

Para aquellos que se preguntan cómo hacer esto con VC no configurados a través del guión gráfico (aquellos que vienen a esta pregunta buscando "programáticamente" + "desenrollar segue").

Dado que no puede configurar una desconexión segmentada programáticamente, la solución programática más simple es llamar a:

navigationController?.popToRootViewController(animated: true)

que mostrará todos los controladores de vista en la pila de nuevo a su controlador de vista raíz.


Para mostrar solo el controlador de vista superior de la pila de navegación, use:

navigationController?.popViewController(animated: true)

10623169
fuente
1
eso suele ser más de lo que desea; para recuperar uno, simplemente haga lo siguiente: [self.navigationController popViewControllerAnimated: YES];
Andy Weinstein
De hecho, he agregado eso a mi respuesta - gracias @AndyWeinstein
10623169
0

FYI: para que la respuesta de @ Vadim funcione con una acción de secuencia de desenrollado manual llamada desde un controlador de vista, debe colocar el comando:

[self performSegueWithIdentifier:(NSString*) identifier sender:(id) sender];

dentro del método de clase anulada viewDidAppear así:

-(void) viewDidAppear:(BOOL) animated
{
    [super viewDidAppear: animated];

    [self performSegueWithIdentifier:@"SomeSegueIdentifier" sender:self];
}

Si lo coloca en otros métodos ViewController como viewDidLoad o viewWillAppear , se ignorará.

John Verco
fuente
3
Definitivamente mal. Llama a performSegueWithIdentifier desde donde quieras.
smileBot
¿No sería esto simplemente desenrollar segue tan pronto como se cargue la vista? En lugar de actuar cuando TÚ quieras, por ejemplo, después de presionar un botón.
Pahnev
@Pahnev sí, lo haría. No sé cómo esta respuesta obtuvo votos positivos. Llamar performSegueWithIdentfierhace exactamente eso: realizar la transición de un ViewController a otro
termina el
Completamente mal. Simplemente se rebobinaría inmediatamente en el lanzamiento.
Lee Probert