Do czego służą klucze Unwind i jak z nich korzystasz?

584

iOS 6 i Xcode 4.5 mają nową funkcję określaną jako „Unwind Segue”:

Sekwencje odwijania mogą umożliwić przejście do istniejących instancji scen w serii ujęć

Oprócz tego krótkiego wpisu w informacjach o wersji Xcode 4.5, UIViewController wydaje się teraz mieć kilka nowych metod:

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

Jak działają sekwensy relaksacyjne i do czego można je wykorzystać?

Imre Kelényi
źródło

Odpowiedzi:

1267

W skrócie

Odpoczynek segue (czasami nazywane wyjściem segue ) może być używany do nawigacji z powrotem przez Push, modalnych lub popover segues (jakbyś wpadł element nawigacyjny z paska nawigacyjnego, zamknął popover lub oddalił modally przedstawione kontroler widoku). Co więcej, możesz odprężyć się nie tylko za pomocą jednego, ale również szeregu poleceń push / modal / popover, np. „Cofnij się” o kilka kroków w hierarchii nawigacji za pomocą pojedynczej operacji cofania.

Kiedy wykonujesz segment odwijania, musisz określić akcję, która jest metodą akcji kontrolera widoku, do której chcesz się odprężyć.

Cel C:

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

Szybki:

@IBAction func unwindToThisViewController(segue: UIStoryboardSegue) {
}

Nazwa tej metody akcji jest używana podczas tworzenia odwijanego segmentu w serii ujęć. Ponadto metoda ta jest wywoływana tuż przed wykonaniem segue odwijania. Możesz pobrać źródłowy kontroler widoku z przekazanego UIStoryboardSegueparametru do interakcji z kontrolerem widoku, który zainicjował segue (np. Aby uzyskać wartości właściwości modalnego kontrolera widoku). Pod tym względem metoda ma podobną funkcję jak prepareForSegue:metoda UIViewController.

Aktualizacja iOS 8: Sekwencje odwijania działają również z sekwencjami adaptacyjnymi iOS 8, takimi jak Pokaż i Pokaż szczegóły .

Przykład

Daj nam scenorys z kontrolerem nawigacyjnym i trzema kontrolerami widoku potomnego:

wprowadź opis zdjęcia tutaj

Z kontrolera Green View możesz odpocząć (nawigacja wstecz) do kontrolera Red View. Z niebieskiego możesz odpocząć do zielonego lub do czerwonego przez zielony. Aby włączyć odwijanie, musisz dodać specjalne metody akcji do czerwonego i zielonego, np. Oto metoda akcji w czerwonym:

Cel C:

@implementation RedViewController

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

@end

Szybki:

@IBAction func unwindToRed(segue: UIStoryboardSegue) {
}

Po dodaniu metody akcji możesz zdefiniować odwijanie w serii ujęć, przeciągając klawiszem Control na ikonę Wyjdź. Tutaj chcemy zrelaksować się do czerwonego z zielonego po naciśnięciu przycisku:

wprowadź opis zdjęcia tutaj

Musisz wybrać akcję zdefiniowaną w kontrolerze widoku, w którym chcesz się zrelaksować:

wprowadź opis zdjęcia tutaj

Możesz także odprężyć się na kolor czerwony z niebieskiego (który znajduje się „dwa kroki dalej” na stosie nawigacji). Kluczem jest wybranie właściwej akcji odwijania.

Przed wykonaniem segmentu odwijania wywoływana jest metoda akcji. W tym przykładzie zdefiniowałem odejście do czerwonego od zielonego i niebieskiego. Możemy uzyskać dostęp do źródła odwijania w metodzie akcji za pomocą parametru UIStoryboardSegue:

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

Szybki:

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

Odwijanie działa również poprzez kombinację sekwencji push / modal. Np. Jeśli dodam inny kontroler widoku żółtego z modalnym segmentem, moglibyśmy odprężyć się od żółtego aż do czerwonego w jednym kroku:

wprowadź opis zdjęcia tutaj

Odwijanie z kodu

Po zdefiniowaniu segregacji odwijania poprzez przeciągnięcie czegoś do symbolu wyjścia kontrolera widoku, nowy kontur pojawia się w konspekcie dokumentu:

wprowadź opis zdjęcia tutaj

Wybranie segmentu i przejście do Inspektora atrybutów ujawnia właściwość „Identyfikator”. Użyj tego, aby nadać unikatowemu identyfikatorowi swój identyfikator:

wprowadź opis zdjęcia tutaj

Następnie można wykonać odwijanie segue z kodu, tak jak każdy inny segment:

Cel C:

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

Szybki:

performSegueWithIdentifier("UnwindToRedSegueID", sender: self)
Imre Kelényi
źródło
12
+1 świetna odpowiedź. Brzmią naprawdę ładnie, ale czy metody takie jak dismissViewControllerAnimated:completion:lub nie mogą popViewControllerAnimated:osiągnąć tego samego?
Sam Spencer
32
Pewnie, że mogą. Jeśli jednak używasz scenorysów, odprężacz może często osiągnąć to samo przy znacznie mniejszym kodzie. W rzeczywistości możesz teraz zamknąć kontroler widoku prezentowany modalnie bez pisania kodu. Oczywiście wciąż jest wiele przypadków, w których zamykanie kontrolerów przed kodem jest właściwym rozwiązaniem.
Imre Kelényi
7
Pamiętaj, aby dodać metodę działania do pliku nagłówka, w przeciwnym razie Storyboard nie będzie wiedział.
Kyle C
17
Kolejną zaletą dismissViewControllerAnimated:completion:lub popViewControllerAnimated:jest to, że wywoływana jest metoda dodana do kontrolera widoku, do którego się odwijasz, dzięki czemu masz łatwy sposób wiedzieć, że prezentowany kontroler widoku jest zakończony bez konieczności zmieniania prezentującego kontrolera widoku w delegata prezentowanego kontrolera widoku .
honus
8
Czy mogę zasugerować niewielką edycję? Nie było „oczywiście” jasne, że umieściłeś - (IBAction) unwindTRed: (UIStoryboardSegue *) unwindSegue w RedViewController.m, a to z kolei jest powszechnie dostępne w „dowolnym” zielonym przycisku wyjścia dowolnej planszy. Fantastyczna odpowiedź, a teraz wykorzystam ją do innych problemów. Dzięki!
John Ballinger
166

Jeśli chodzi o korzystanie z sekwencji rozwijania w StoryBoard ...

Krok 1)

Przejdź do kodu kontrolera widoku, do którego chcesz się odprężyć, i dodaj to:

Cel C

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

Należy również zadeklarować tę metodę w pliku .h w Obj-C

Szybki

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

Krok 2)

W scenorysie przejdź do widoku, z którego chcesz się zrelaksować, i po prostu przeciągnij segue z przycisku lub cokolwiek do małej pomarańczowej ikony „WYJŚCIE” w prawym górnym rogu widoku źródłowego.

wprowadź opis zdjęcia tutaj

Powinna być teraz opcja połączenia z „--indindToViewControllerNameHere”

To wszystko, Twój segue odpręży się po naciśnięciu przycisku.

Travis M.
źródło
5
Odkryłem, że w Xcode 4.5 i wcześniejszych konieczne było zadeklarowanie IBAction w nagłówku. Nie wiem czy to nadal prawda.
Steven Fisher
2
Czy istnieje sposób na wykonanie kroku 2 bez scenorysu, tj. Programowo? Mój scenorys (konstruktor interfejsów) jest zawalony i nie pokazuje sekwencji rozwijania (błąd xcode).
Van Du Tran
46

Sekwencje odwijania są używane do „powrotu” do jakiegoś kontrolera widoku, z którego poprzez szereg sekwencji można przejść do „bieżącego” kontrolera widoku.

Wyobraź sobie, że masz coś MyNavControllerz Akontrolerem widoku głównego. Teraz używasz push push do B. Teraz kontroler nawigacyjny ma w swojej viewControllerstablicy A i B , a B jest widoczne. Teraz się prezentujeszC modalnie.

Dzięki sekwencjom odprężania można teraz odprężyć „wstecz” od Cdo B(tj. Odrzucając przedstawiony modalnie kontroler widoku), po prostu „cofając” segregację modalną. Możesz nawet zrelaksować się z powrotem do kontrolera widoku głównego A, cofając zarówno segment modalny, jak i segment push.

Sekwens odwijania ułatwia cofanie się. Na przykład przed iOS 6 najlepszą praktyką do odrzucania prezentowanych kontrolerów widoku było ustawienie kontrolera widoku prezentującego jako delegata prezentowanego kontrolera widoku, a następnie wywołanie niestandardowej metody delegowania, która następnie zwalnia przedstawionego kontrolera widoku . Brzmi niewygodny i skomplikowany? To było. Właśnie dlatego odprężające segue są fajne.

Yang Meyer
źródło
7
Możesz zadzwonić dismissViewController:animatedz przedstawionego kontrolera. Nie musisz tego delegować. Oczywiście, jeśli chcesz przekazać dane z powrotem, potrzebujesz delegacji lub innej metody.
mxcl
3
Chociaż możesz zadzwonić dismissViewController:animated:z prezentowanego kontrolera, „najlepszą praktyką” było rzeczywiście wywołanie metody delegowania na kontrolerze prezentującym, aby zrobić to za ciebie, jak wspomniał Yang.
Chris Nolet
36

Coś, o czym nie wspomniałem w innych odpowiedziach tutaj, to sposób radzenia sobie z rozwijaniem się, gdy nie wiesz, skąd pochodzi początkowy segment, co jest dla mnie jeszcze ważniejszym przypadkiem użycia. Załóżmy na przykład, że masz kontroler widoku pomocy ( H ), który wyświetlasz modalnie z dwóch różnych kontrolerów widoku ( A i B ):

AH
BH

Jak skonfigurować segment odwijania, aby wrócić do właściwego kontrolera widoku? Odpowiedź jest taka, że ​​deklarujesz akcję odwijania w A i B o tej samej nazwie , np .:

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

W ten sposób odprężenie znajdzie dowolny kontroler widoku ( A lub B ), który zainicjował segue i wróci do niego.

Innymi słowy, myślę o odwijania działania jako opisujące gdzie segue przychodzi od , raczej niż gdzie to będzie.

shawkinaw
źródło
2
Dzięki za te informacje, szukałem tego.
Madhu,
2
wspaniale jest wspomnieć o tych informacjach, ponieważ już wdrażam to rozwiązanie i nic się nie dzieje, dopóki nie otrzymam porady, dzięki bardzo za wsparcie
Amr Angry
To świetna informacja! Dziękuję Ci bardzo!
Dominique Vial
24

Swift iOS:

Krok 1: zdefiniuj tę metodę w widoku kontrolera MASTER. w którym chcesz wrócić:

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

    println("Called goToSideMenu: unwind action")

}

Krok 2: (StoryBoard) Kliknij prawym przyciskiem myszy przycisk SLAVE / CHILD EXIT i wybierz „goToSideMenu” jako czynność, aby połączyć Cię Przycisk, na którym klikniesz, aby powrócić do widoku kontrolera MASTER:

wprowadź opis zdjęcia tutaj krok 3: Zbuduj i uruchom ...

Vinod Joshi
źródło
1

Na przykład, jeśli nawigujesz z viewControllerB do viewControllerA, to w twoim viewControllerA poniżej delegat zadzwoni i dane będą udostępniane.

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

}
  • Unwind Seague Source View Controller (musisz podłączyć przycisk wyjścia do ikony wyjścia VC i połączyć go z nieświadomością:

wprowadź opis zdjęcia tutaj

  • Unwind Seague Completed -> TextLabel of viewControllerA został zmieniony.

wprowadź opis zdjęcia tutaj

Tech
źródło