Para que servem os seguidores do Unwind e como você os usa?

584

O iOS 6 e o ​​Xcode 4.5 possuem um novo recurso chamado "Descontrair segmento":

Desenrolar segues pode permitir a transição para instâncias existentes de cenas em um storyboard

Além dessa breve entrada nas notas de versão do Xcode 4.5, o UIViewController agora parece ter alguns métodos novos:

- (BOOL)canPerformUnwindSegueAction:(SEL)action fromViewController:(UIViewController *)fromViewController withSender:(id)sender
- (UIViewController *)viewControllerForUnwindSegueAction:(SEL)action fromViewController:(UIViewController *)fromViewController withSender:(id)sender
- (UIStoryboardSegue *)segueForUnwindingToViewController:(UIViewController *)toViewController fromViewController:(UIViewController *)fromViewController identifier:(NSString *)identifier

Como funcionam os desenroladores segues e para que podem ser usados?

Imre Kelényi
fonte

Respostas:

1267

Em poucas palavras

Um segue de desenrolamento (às vezes chamado de segue de saída ) pode ser usado para navegar de volta através de seguimentos push, modal ou popover (como se você tivesse retirado o item de navegação da barra de navegação, fechou o popover ou dispensou o controlador de exibição apresentado modalmente). Além disso, você pode realmente relaxar não apenas uma, mas uma série de seguimentos push / modal / popover, por exemplo, "voltar" várias etapas na hierarquia de navegação com uma única ação de relaxamento.

Ao executar uma sequência de desenrolamento, é necessário especificar uma ação, que é um método de ação do controlador de exibição em que você deseja descontrair.

Objetivo-C:

- (IBAction)unwindToThisViewController:(UIStoryboardSegue *)unwindSegue
{
}

Rápido:

@IBAction func unwindToThisViewController(segue: UIStoryboardSegue) {
}

O nome desse método de ação é usado quando você cria as etapas de desenrolamento no storyboard. Além disso, esse método é chamado pouco antes da execução do desenrolamento. Você pode fazer com que o controlador de visualização de origem, a partir do UIStoryboardSegueparâmetro passado, interaja com o controlador de visualização que iniciou o segue (por exemplo, para obter os valores de propriedade de um controlador de visualização modal). A este respeito, o método tem uma função semelhante ao prepareForSegue:método de UIViewController.

Atualização do iOS 8: os desenrolamentos de desenrolamento também funcionam com os adaptativos do iOS 8, como Mostrar e Mostrar detalhes .

Um exemplo

Vamos criar um storyboard com um controlador de navegação e três controladores de exibição filho:

insira a descrição da imagem aqui

No Green View Controller, você pode relaxar (navegar de volta) para o Red View Controller. Do azul, você pode relaxar para verde ou vermelho via verde. Para ativar o desenrolamento, você deve adicionar os métodos de ação especiais a Vermelho e Verde, por exemplo, aqui está o método de ação em Vermelho:

Objetivo-C:

@implementation RedViewController

- (IBAction)unwindToRed:(UIStoryboardSegue *)unwindSegue
{
}

@end

Rápido:

@IBAction func unwindToRed(segue: UIStoryboardSegue) {
}

Após a adição do método de ação, você pode definir as etapas de desenrolamento no storyboard arrastando a tecla Control até o ícone Sair. Aqui, queremos desanuviar do vermelho para o verde quando o botão é pressionado:

insira a descrição da imagem aqui

Você deve selecionar a ação que é definida no controlador de exibição que deseja descontrair:

insira a descrição da imagem aqui

Você também pode relaxar com o Red from Blue (que fica a "dois passos" na pilha de navegação). A chave é selecionar a ação de desenrolar correta.

Antes da execução do desenrolamento, o método de ação é chamado. No exemplo, eu defini um desenrolar segue para vermelho de verde e azul. Podemos acessar a fonte do desenrolar no método de ação através do parâmetro UIStoryboardSegue:

Objetivo-C:

- (IBAction)unwindToRed:(UIStoryboardSegue *)unwindSegue
{
    UIViewController* sourceViewController = unwindSegue.sourceViewController;

    if ([sourceViewController isKindOfClass:[BlueViewController class]])
    {
        NSLog(@"Coming from BLUE!");
    }
    else if ([sourceViewController isKindOfClass:[GreenViewController class]])
    {
        NSLog(@"Coming from GREEN!");
    }
}

Rápido:

@IBAction func unwindToRed(unwindSegue: UIStoryboardSegue) {
    if let blueViewController = unwindSegue.sourceViewController as? BlueViewController {
        println("Coming from BLUE")
    }
    else if let redViewController = unwindSegue.sourceViewController as? RedViewController {
        println("Coming from RED")
    }
}

Desenrolar também funciona através de uma combinação de push / modal segues. Por exemplo, se eu adicionasse outro controlador de exibição Yellow com um segue modal, poderíamos relaxar do Yellow até o Red em uma única etapa:

insira a descrição da imagem aqui

Desenrolando do Código

Quando você define um segue de desenrolar ao arrastar algo para o símbolo Exit de um controlador de exibição, um novo segue aparece no Esboço do documento:

insira a descrição da imagem aqui

Selecionar as instruções e ir para o Inspetor de atributos revela a propriedade "Identificador". Use isso para fornecer um identificador exclusivo para seus seguimentos:

insira a descrição da imagem aqui

Depois disso, os passos descontraídos podem ser executados a partir do código, como qualquer outro segue:

Objetivo-C:

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

Rápido:

performSegueWithIdentifier("UnwindToRedSegueID", sender: self)
Imre Kelényi
fonte
12
+1 ótima resposta. Eles parecem muito bons, mas os métodos não podem gostar dismissViewControllerAnimated:completion:ou popViewControllerAnimated:alcançar a mesma coisa?
Sam Spencer
32
Claro que podem. No entanto, se você estiver usando storyboards, os desenroladores de seguidores geralmente podem obter a mesma coisa com muito menos código. Na verdade, agora você pode descartar um controlador de exibição apresentado de forma modal sem escrever nenhum código. Obviamente, ainda existem muitos casos em que o fechamento de controladores a partir do código é a coisa certa a se fazer.
Imre Kelényi
7
Certifique-se de adicionar seu método de ação ao seu arquivo de cabeçalho, caso contrário o Storyboard não saberá.
Kyle C
17
Outra vantagem sobre dismissViewControllerAnimated:completion:ou popViewControllerAnimated:é que o método que você adicionou ao controlador de exibição para o qual você está desenrolando é chamado e, assim, você tem uma maneira fácil de saber que o controlador de exibição apresentado foi concluído sem precisar fazer do controlador de exibição apresentador um delegado do controlador de exibição apresentado .
honus
8
Posso sugerir uma ligeira edição? Não ficou "obviamente" claro que você colocou - (IBAction) desanuviado: (UIStoryboardSegue *) desenrolou-se no RedViewController.m e, por sua vez, está universalmente disponível em "qualquer" dos botões de saída verdes de qualquer quadro de histórias. Resposta fantástica e agora vou usar isso para outros problemas. Obrigado!
John Ballinger
166

No que diz respeito a como usar desenroladores seguidos no StoryBoard ...

Passo 1)

Vá para o código do controlador de exibição que você deseja descontrair e adicione isto:

Objetivo-C

- (IBAction)unwindToViewControllerNameHere:(UIStoryboardSegue *)segue {
    //nothing goes here
}

Certifique-se de também declarar esse método no seu arquivo .h no Obj-C

Rápido

@IBAction func unwindToViewControllerNameHere(segue: UIStoryboardSegue) {
    //nothing goes here
}

Passo 2)

No storyboard, acesse a visualização da qual deseja relaxar e simplesmente arraste uma sequência do seu botão ou o que quer que seja até o pequeno ícone laranja "EXIT" no canto superior direito da visualização de origem.

insira a descrição da imagem aqui

Agora deve haver uma opção para se conectar a "- unwindToViewControllerNameHere"

É isso aí, seus passos serão desenrolados quando o botão for pressionado.

Travis M.
fonte
5
Descobri que, com o Xcode 4.5 e versões anteriores, era necessário declarar o IBAction no cabeçalho. Não sei se isso ainda é verdade.
Steven Fisher
2
Existe uma maneira de executar a Etapa 2 sem storyboard, ou seja, programaticamente? Meu storyboard (construtor de interface) está bagunçado e não mostra as sequências de desenrolamento (bug do xcode).
Van Du Tran
46

Os desenrolamentos de desenrolamento são usados ​​para "voltar" a algum controlador de exibição do qual, através de várias etapas, você chegou ao controlador de exibição "atual".

Imagine que você tem algo um MyNavControllercom Acomo seu controlador de vista raiz. Agora você usa um push segue para B. Agora o controlador de navegação possui A e B em sua viewControllersmatriz, e B está visível. Agora você apresenta Cmodalmente.

Com os desenrolamentos seguidos, agora você pode retroceder "voltar" de Cpara B(ou seja, descartar o controlador de exibição apresentado modalmente), basicamente "desfazendo" o segue modal. Você pode até voltar ao controlador de visualização raiz A, desfazendo o segue modal e o push segue.

Desenrolar os passos facilita o retorno. Por exemplo, antes do iOS 6, a melhor prática para descartar os controladores de exibição apresentados era definir o controlador de exibição de apresentação como delegado do controlador de exibição apresentado e, em seguida, chamar seu método delegado personalizado, que dispensa o apresentadoViewController . Parece complicado e complicado? Isso foi. É por isso que descontrair segues é bom.

Yang Meyer
fonte
7
Você pode ligar dismissViewController:animateddo controlador apresentado. Você não precisa delegar isso. Obviamente, se você precisar transmitir dados, precisará de delegação ou outro método.
Mxcl 26/09/13
3
Embora você possa ligar dismissViewController:animated:do controlador apresentado, a "melhor prática" era chamar um método delegado no controlador de apresentação para fazer isso por você, como Yang mencionou.
Chris Nolet
36

Algo que eu não vi mencionado nas outras respostas aqui é como você lida com o desenrolamento quando não sabe onde a sequência inicial se originou, o que para mim é um caso de uso ainda mais importante. Por exemplo, digamos que você tenha uma ajuda para visualizar o controlador ( H ) exibido de forma modal a partir de dois controladores de exibição diferentes ( A e B ):

AH
BH

Como você configura as instruções de desenrolamento para voltar ao controlador de exibição correto? A resposta é que você declara uma ação de desenrolamento em A e B com o mesmo nome , por exemplo:

// put in AViewController.swift and BViewController.swift
@IBAction func unwindFromHelp(sender: UIStoryboardSegue) {
    // empty
}

Dessa forma, o desenrolamento encontrará o controlador de visualização ( A ou B ) que iniciou o segue e retornará a ele.

Em outras palavras, pensar a ação desenrola como descrevendo onde o segue está vindo de , ao invés de onde ele está indo.

shawkinaw
fonte
2
Obrigado por esta informação, eu estava procurando por isso.
Madhu
2
É realmente muito bom para mencionar esta informação como eu já implementação da solução e nada acontecer até que eu obter a sua dica aqui muito obrigado por seu apoio
Amr irritado
Esta é uma excelente informação! Muito obrigado!
Dominique Vial
24

IOS rápido:

Etapa 1: defina esse método na visualização do controlador MASTER. em que você deseja voltar:

//pragma mark - Unwind Seques
@IBAction func goToSideMenu(segue: UIStoryboardSegue) {

    println("Called goToSideMenu: unwind action")

}

Etapa 2: (StoryBoard) Clique com o botão direito do mouse no botão SLAVE / CHILD EXIT e selecione "goToSideMenu" Como ação no botão Connect you no qual você clicará para retornar à visualização do controlador MASTER:

insira a descrição da imagem aqui Etapa 3: criar e executar ...

Vinod Joshi
fonte
1

Por exemplo, se você navegar do viewControllerB para o viewControllerA, no delegado viewControllerA abaixo, você será chamado e os dados serão compartilhados.

@IBAction func unWindSeague (_ sender : UIStoryboardSegue) {
        if sender.source is ViewControllerB  {
            if let _ = sender.source as? ViewControllerB {
                self.textLabel.text = "Came from B = B->A , B exited"
            }
            
        }

}
  • Descontraia o controlador de exibição da fonte do Seague (é necessário conectar o botão Sair ao ícone de saída do VC e conectá-lo ao desenrolar da conversa:

insira a descrição da imagem aqui

  • Desanuviar Seague Completed -> TextLabel de viewControllerA é alterado.

insira a descrição da imagem aqui

Tecnologia
fonte