A cosa servono i seguaci Unwind e come li usi?


584

iOS 6 e Xcode 4.5 ha una nuova funzionalità denominata "Unwind Segue":

I seguaci Unwind possono consentire il passaggio a istanze esistenti di scene in uno storyboard

Oltre a questa breve voce nelle note di rilascio di Xcode 4.5, UIViewController ora sembra avere un paio di nuovi metodi:

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

Come funzionano i seguaci di svolgimento e per cosa possono essere utilizzati?

Risposte:


1267

In breve

Segue uno svolgersi (a volte chiamato exit segue ) può essere utilizzato per tornare indietro attraverso follow, push modali o popover (come se si estraesse l'elemento di navigazione dalla barra di navigazione, si chiudesse il popover o si eliminasse il controller di visualizzazione presentato in modo modale). Inoltre, puoi effettivamente rilassarti non solo attraverso una, ma una serie di follower push / modal / popover, ad esempio "tornare indietro" di più passaggi nella gerarchia di navigazione con una singola azione di svolgimento.

Quando si esegue un svolgimento segue, è necessario specificare un'azione, che è un metodo di azione del controller di visualizzazione che si desidera svolgere.

Objective-C:

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

Swift:

@IBAction func unwindToThisViewController(segue: UIStoryboardSegue) {
}

Il nome di questo metodo di azione viene utilizzato quando si crea lo svolgimento segue nello storyboard. Inoltre, questo metodo viene chiamato poco prima che venga eseguito lo svolgimento. È possibile ottenere il controller della vista di origine dal UIStoryboardSegueparametro passato per interagire con il controller di vista che ha avviato il seguito (ad es. Per ottenere i valori delle proprietà di un controller di vista modale). A questo proposito, il metodo ha una funzione simile al prepareForSegue:metodo di UIViewController.

Aggiornamento iOS 8: i segui Unwind funzionano anche con i segui adattivi di iOS 8, come Mostra e Mostra dettagli .

Un esempio

Facciamo uno storyboard con un controller di navigazione e tre controller di visualizzazione figlio:

inserisci qui la descrizione dell'immagine

Da Green View Controller puoi rilassarti (tornare indietro) a Red View Controller. Dal blu puoi rilassarti al verde o al rosso tramite il verde. Per abilitare lo svolgimento è necessario aggiungere i metodi di azione speciali a Rosso e Verde, ad esempio qui è il metodo di azione in Rosso:

Objective-C:

@implementation RedViewController

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

@end

Swift:

@IBAction func unwindToRed(segue: UIStoryboardSegue) {
}

Dopo aver aggiunto il metodo di azione, è possibile definire i seguenti svolgimenti nello storyboard trascinando il controllo sull'icona Esci. Qui vogliamo rilassarci al rosso dal verde quando si preme il pulsante:

inserisci qui la descrizione dell'immagine

È necessario selezionare l'azione definita nel controller di visualizzazione che si desidera svolgere:

inserisci qui la descrizione dell'immagine

Puoi anche rilassarti in Rosso da Blu (che è "a due passi" nello stack di navigazione). La chiave sta selezionando l'azione di svolgimento corretta.

Prima di eseguire lo svolgersi, viene chiamato il metodo di azione. Nell'esempio che ho definito, uno svolgersi segue il rosso sia dal verde che dal blu. Possiamo accedere alla fonte del svolgersi nel metodo di azione tramite il parametro UIStoryboardSegue:

Objective-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!");
    }
}

Swift:

@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")
    }
}

Unwinding funziona anche attraverso una combinazione di follow / push modali. Ad esempio, se ho aggiunto un altro controller di visualizzazione Yellow con un seguito modale, potremmo tornare da Yellow a Red in un unico passaggio:

inserisci qui la descrizione dell'immagine

Rilassarsi dal codice

Quando si definisce un seguito di svolgimento svolgendo il controllo e trascinando qualcosa sul simbolo Exit di un controller di visualizzazione, nel profilo documento viene visualizzato un nuovo seguito:

inserisci qui la descrizione dell'immagine

Selezionando il seguito e andando su Impostazioni Attributi si rivela la proprietà "Identificatore". Usa questo per dare un identificatore univoco al tuo seguito:

inserisci qui la descrizione dell'immagine

Dopodiché, lo svolgimento di svolgersi può essere eseguito dal codice proprio come qualsiasi altro segue:

Objective-C:

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

Swift:

performSegueWithIdentifier("UnwindToRedSegueID", sender: self)

12
+1 ottima risposta. Sembrano davvero carini, ma i metodi non possono piacere dismissViewControllerAnimated:completion:o popViewControllerAnimated:ottenere la stessa cosa?
Sam Spencer,

32
Sicuro che possono. Tuttavia, se si utilizzano storyboard, i seguaci di svolgersi spesso possono ottenere la stessa cosa con molto meno codice. In realtà, ora puoi eliminare un controller di visualizzazione presentato in modo modale senza scrivere alcun codice. Naturalmente, ci sono ancora molti casi in cui chiudere i controller dal codice è la cosa giusta da fare.
Imre Kelényi,

7
Assicurati di aggiungere il tuo metodo di azione al file di intestazione, altrimenti Storyboard non lo saprà.
Kyle C,

17
Un altro vantaggio rispetto dismissViewControllerAnimated:completion:o popViewControllerAnimated:è che viene chiamato il metodo che hai aggiunto al controller di vista a cui non ti stai svolgendo e quindi hai un modo semplice per sapere che il controller di vista presentato è finito senza dover rendere il controller di vista presentatore un delegato del controller di vista presentato .
honus,

8
Potrei suggerire una leggera modifica? Non è stato "ovviamente" chiaro che tu abbia inserito - (IBAction) unindTRed: (UIStoryboardSegue *) unwindSegue in RedViewController.m, e questo a sua volta è universalmente disponibile in "qualsiasi" dei pulsanti di uscita verdi per qualsiasi storyboard. Risposta fantastica e ora la userò per altri problemi. Grazie!
John Ballinger,

166

Per quanto riguarda come utilizzare seguaci di svolgimento in StoryBoard ...

Passo 1)

Vai al codice per il controller di visualizzazione che desideri rilassare e aggiungi questo:

Objective-C

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

Assicurati di dichiarare anche questo metodo nel tuo file .h in Obj-C

veloce

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

Passo 2)

Nello storyboard, vai alla vista da cui vuoi rilassarti e trascina semplicemente un seguito dal tuo pulsante o qualsiasi altra cosa fino alla piccola icona arancione "EXIT" nella parte superiore destra della vista sorgente.

inserisci qui la descrizione dell'immagine

Ora dovrebbe esserci un'opzione per connettersi a "- unwindToViewControllerNameHere"

Ecco fatto, il tuo seguito si svolgerà quando si tocca il pulsante.


5
Ho scoperto che con Xcode 4.5 e precedenti era necessario dichiarare l'IBAction nell'intestazione. Non so se questo sia ancora vero.
Steven Fisher,

2
C'è un modo per fare il passo 2 senza storyboard, cioè a livello di programmazione? Il mio storyboard (generatore di interfacce) è incasinato e non mostra i segues di svolgimento (bug xcode).
Van Du Tran,

46

I segues Unwind sono usati per "tornare indietro" ad alcuni controller di visualizzazione da cui, attraverso un numero di segues, si è arrivati ​​al controller di visualizzazione "corrente".

Immaginate di avere qualcosa di un MyNavControllercon Ala sua radice controller della vista. Ora usi una spinta seguita da B. Ora il controller di navigazione ha A e B nel suo viewControllersarray e B è visibile. Ora presenti in Cmodale.

Con unfind segues , ora è possibile svolgere "back" da Ca B(ovvero eliminare il controller di visualizzazione presentato in modo modale), sostanzialmente "annullare" il follow modale. Potresti anche rilassarti fino al controller della vista principale A, annullando sia il seguito modale che il push segue.

I segues Unwind rendono facile tornare indietro. Ad esempio, prima di iOS 6, la migliore pratica per eliminare i controller di visualizzazione presentati era impostare il controller di visualizzazione della presentazione come delegato del controller di visualizzazione presentato, quindi chiamare il metodo del delegato personalizzato, che quindi elimina il ViewViewController presentato . Sembra ingombrante e complicato? Era. Ecco perché i seguaci di svolgersi sono carini.


7
Puoi chiamare dismissViewController:animateddal controller presentato. Non devi delegarlo. Naturalmente, se è necessario restituire i dati, è necessaria la delega o un altro metodo.
mxcl,

3
Mentre è possibile chiamare dismissViewController:animated:dal controller presentato, "best practice" era effettivamente chiamare un metodo delegato sul controller presentatore per farlo per te, come ha detto Yang.
Chris Nolet,

36

Qualcosa che non ho visto menzionato nelle altre risposte qui è come affrontare lo svolgersi quando non si sa dove ha avuto origine il seguito iniziale, che per me è un caso d'uso ancora più importante. Ad esempio, supponiamo che tu abbia un controller di visualizzazione della guida ( H ) che visualizzi modalmente da due controller di visualizzazione diversi ( A e B ):

AH
BH

Come si configura lo svolgimento di svolgimento in modo da tornare al controller di visualizzazione corretto? La risposta è dichiarare un'azione di svolgimento in A e B con lo stesso nome , ad esempio:

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

In questo modo, lo svolgitore troverà qualunque controller di visualizzazione ( A o B ) avviato e seguirà nuovamente.

In altre parole, pensare l'azione di svolgimento a descrivere dove la segue proviene da , piuttosto che dove sta andando.


2
Grazie per queste informazioni, stavo cercando questo.
Madhu,

2
è davvero bello menzionare queste informazioni poiché sto già implementando la soluzione e non succede nulla finché non avrò il tuo consiglio qui grazie mille per il tuo supporto
Amr Angry

Questa è una grande informazione! Grazie mille!
Dominique Vial,

24

Swift iOS:

Passaggio 1: definire questo metodo nella vista del controller MASTER. in cui vuoi tornare indietro:

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

    println("Called goToSideMenu: unwind action")

}

Passaggio 2: (StoryBoard) Fare clic con il pulsante destro del mouse sul pulsante SLAVE / CHILD EXIT e selezionare "goToSideMenu" Come azione per connetterti Pulsante su cui fare clic per tornare alla visualizzazione del controller MASTER:

inserisci qui la descrizione dell'immagine passaggio 3: compilare ed eseguire ...


1

Ad esempio, se navighi da viewControllerB a viewControllerA, nel tuo viewControllerA sotto il delegato chiamerà e i dati verranno condivisi.

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

}
  • Sblocca controller vista sorgente Seague (devi connettere il pulsante Exit all'icona di uscita di VC e collegarlo a unwindseague:

inserisci qui la descrizione dell'immagine

  • Unwind Seague Completed -> TextLabel of viewControllerA è cambiato.

inserisci qui la descrizione dell'immagine

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.