Для чого потрібні розмотки і як ви їх використовуєте?


584

iOS 6 та Xcode 4.5 має нову функцію, яку називають "відмотка Segue":

Розмотування невдач може дозволити перехід до наявних екземплярів сцен у розкадровці

Окрім цього короткого запису у примітках до випуску Xcode 4.5, тепер, здається, UIViewController має ще кілька нових методів:

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

Як працюють розмотані сеги та для чого їх можна використовувати?

Відповіді:


1267

Коротко

Розмотування переходу (іноді званий вихід Segue ) можна використовувати для переміщення вперед через поштовх, модальні або поповеров перетікає (як якщо б ви сунули навігаційний елемент з панелі навігації, закрили поповеров або відхилили модально представлений контролер уявлення). Крім того, ви можете реально розкручуватись не лише одним, а серією натискань / модальних / перехожих перешкод, наприклад, "повернення" декількома кроками у вашій ієрархії навігації одним дією розмотування.

Виконуючи розмотувальний мозок, вам потрібно вказати дію, яка є методом дії контролера перегляду, який ви хочете відкрутити.

Завдання-C:

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

Швидкий:

@IBAction func unwindToThisViewController(segue: UIStoryboardSegue) {
}

Назва цього методу дії використовується, коли ви створюєте розмотаний мозок у таблиці розмов. Крім того, цей метод застосовується безпосередньо перед тим, як буде проведено розмотувальний розтин. Ви можете отримати контролер подання джерела від переданого UIStoryboardSegueпараметра для взаємодії з контролером подання, який ініціював segue (наприклад, для отримання значень властивостей контролера модального перегляду). У цьому відношенні метод має аналогічну функцію, як prepareForSegue:метод UIViewController.

Оновлення iOS 8: Розмотування зразків також працює з адаптивними групами iOS 8, такими як Show and Show Detail .

Приклад

Будемо мати табло з навігаційним контролером та трьома контролерами дитячого перегляду:

введіть тут опис зображення

З Контролера зеленого перегляду ви можете розмотати (перейти назад) до контролера Red View. З синього ви можете розмотатися на зелений або червоний через зелений. Щоб увімкнути розмотування, слід додати спеціальні методи дій до червоного та зеленого, наприклад ось метод дії червоним:

Завдання-C:

@implementation RedViewController

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

@end

Швидкий:

@IBAction func unwindToRed(segue: UIStoryboardSegue) {
}

Після того, як метод дії буде додано, ви можете визначити розмотаний мозок на дошці розкадрування, перетягуючи його до значка «Вихід». Тут ми хочемо відмовитись від червоного від зеленого при натисканні кнопки:

введіть тут опис зображення

Ви повинні вибрати дію, визначену в контролері перегляду, який ви хочете відмовити:

введіть тут опис зображення

Ви також можете відмовитись від червоного від синього (який знаходиться в двох кроках у навігаційному стеку). Ключовим моментом є вибір правильної дії на розмотування.

Перед тим, як проводити розмотувальний розтин, називається метод дії. У прикладі я визначив, що розгортається червоний колір із Зеленого та Синього. Ми можемо отримати доступ до джерела розмотування в методі дії за допомогою параметра UIStoryboardSegue:

Завдання-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!");
    }
}

Швидкий:

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

Розмотування також працює за допомогою комбінації натискань / модальних швів. Наприклад, якщо я додав ще один контролер жовтого виду з модальним швом, ми могли б відмовитися від Жовтого аж до Червоного за один крок:

введіть тут опис зображення

Відмотування від кодексу

Коли ви визначаєте розмотуючий мозок, перетягуючи щось до символу Exit контролера перегляду, в конфігурації документа з'являється новий вираз:

введіть тут опис зображення

Вибір сейфа та перехід до інспектора атрибутів виявляє властивість "Ідентифікатор". Використовуйте це, щоб надати унікальний ідентифікатор вашому модному каналу:

введіть тут опис зображення

Після цього розгортання мозку може бути виконано з коду, як і будь-яке інше:

Завдання-C:

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

Швидкий:

performSegueWithIdentifier("UnwindToRedSegueID", sender: self)

12
+1 чудова відповідь. Вони звучать по-справжньому приємно, але хіба методи не можуть подобатися dismissViewControllerAnimated:completion:чи popViewControllerAnimated:досягати того самого?
Сем Спенсер

32
Звичайно, вони можуть. Однак, якщо ви використовуєте мовленнєві дошки, розмотані сеги часто можуть досягти того ж, що значно менший код. Насправді тепер ви можете відхилити модально представлений контролер перегляду, не записуючи жодного коду. Звичайно, є ще багато випадків, коли закриття контролерів від коду - це правильно зробити.
Імре Келеній

7
Не забудьте додати спосіб дії до файлу заголовка, інакше дошка Storyboard не знатиме.
Кайл C

17
Ще одна перевага перед dismissViewControllerAnimated:completion:або popViewControllerAnimated:полягає в тому, що метод, який ви додали до контролера перегляду, який ви розмотуєте, викликається, і тому у вас є простий спосіб дізнатися представлений контролер подання, закінчується без необхідності зробити контролер подання подання делегатом представленого контролера перегляду .
honus

8
Чи можу я запропонувати невелику редагування? Не було "очевидно" зрозуміло, що ви ставите - (IBAction) unindTRed: (UIStoryboardSegue *) unindSegue в RedViewController.m, і, в свою чергу, це є загальнодоступним у "будь-якому" із зелених кнопок виходу на будь-яку дошку історії. Фантастична відповідь, і зараз я використаю це для інших питань. Дякую!
Джон Баллінгер

166

Що стосується того, як використовувати розмотані сеги в StoryBoard ...

Крок 1)

Перейдіть до коду контролера перегляду, який ви хочете відкрутити, і додайте це:

Ціль-С

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

Не забудьте також оголосити цей метод у своєму .h файлі в Obj-C

Швидкий

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

Крок 2)

У дошці розкадрування перейдіть до подання, від якого ви хочете відпочити, і просто перетягніть вигляд із кнопки або будь-якого іншого до маленького помаранчевого піктограми "EXIT" у верхньому правому куті подання джерела.

введіть тут опис зображення

Тепер має бути можливість підключитися до "- undindToViewControllerNameHere"

Ось так, ваш моторол розмотається, коли натискає кнопку.


5
Я виявив, що з Xcode 4.5 і раніше потрібно було оголосити IBAction в заголовку. Я не знаю, чи це все-таки правда.
Стівен Фішер

2
Чи є спосіб зробити крок 2 без розгортки, тобто програмно? Моя розгортка (конструктор інтерфейсу) заплутана, і на ній не відображаються розмотані сеги (помилка xcode).
Ван Дю Тран

46

Розмотування сег використовується для "повернення" до якогось контролера перегляду, з якого через низку Seges ви потрапили до "поточного" контролера перегляду.

Уявіть, що у вас є щось MyNavControllerз Aяк його контролер кореневого перегляду. Тепер ви використовуєте натискаючий segue для B. Тепер навігаційний контролер має A і B у своєму viewControllersмасиві, і B видно. Тепер ви представляєтесь Cмодально.

З UNWIND перетікає, ви тепер могли розслабитися «назад» від Cдо B(тобто відхиляючи модально , представлений контролер уявлення), в основному «скасовуючи» модальний SEGUE. Ви навіть можете розмотатися повністю до кореневого контролера A, скасовуючи як модальний, так і натискаючий.

Розмотування неприємних змагань полегшує відстеження. Наприклад, перед iOS 6 найкращою практикою для відхилення представлених контролерів подання було встановити контролер подання подання як делегат представленого контролера подання, а потім викликати власний метод делегування, який потім відхиляє представленийViewController . Звучить громіздко і складно? Це було. Ось чому приємно розмотати сеги.


7
Ви можете зателефонувати dismissViewController:animatedз представленого контролера. Не потрібно це делегувати. Звичайно, якщо вам потрібно передати дані назад, тоді вам потрібно делегування або якийсь інший метод.
mxcl

3
Хоча ви можете зателефонувати dismissViewController:animated:з представленого контролера, "найкращою практикою" було дійсно викликати метод делегата на представленому контролері, щоб зробити це для вас, як згадував Ян.
Кріс Нолет

36

Те, що я не бачив згадуваних в інших відповідях тут, - це те, як ви маєте справу з розмотуванням, коли не знаєте, звідки виник первісний вираз, що для мене є ще важливішим випадком використання. Наприклад, скажімо, у вас є контролер подання довідки ( H ), який ви модально відображаєте з двох різних контролерів перегляду ( A і B ):

AH
BH

Як налаштувати розмотувальний мозок, щоб повернутися до правильного контролера перегляду? Відповідь полягає в тому, що ви оголошуєте розгорнуту дію в A і B з однойменними назвами , наприклад:

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

Таким чином, розмотання знайде той, який контролер перегляду ( A або B ) ініціював segue і повернеться до нього.

Іншими словами, думати про розмотування дії як опису , де перехід йде від , а не там , де вона збирається.


2
Дякую за цю інформацію, я шукав це.
Мадху

2
дійсно чудово згадувати цю інформацію, оскільки я вже впроваджую рішення, і нічого не трапиться, поки я не отримаю ваші поради, дякую за вашу підтримку
Amr Angry

Це чудова інформація! Дуже дякую!
Домінік Віал

24

Швидкий iOS:

Крок 1: визначте цей метод у поданні контролера MASTER. в який ви хочете повернутися:

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

    println("Called goToSideMenu: unwind action")

}

Крок 2: (StoryBoard) Клацніть правою кнопкою миші на кнопку SLAVE / CHILD EXIT і виберіть «goToSideMenu» як дію, щоб підключити кнопку, на якій ви натиснете, щоб повернутися до вас з виду контролера MASTER:

введіть тут опис зображення крок 3: Створення та запуск ...


1

Наприклад, якщо ви переходите з viewControllerB до viewControllerA, то у вашому viewControllerA нижче делегат зателефонує, і дані поділяться.

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

}
  • Розмотайте контролер подання джерела Seague (Вам потрібно підключити кнопку виходу до піктограми виходу VC та підключити її до розмовки:

введіть тут опис зображення

  • Розмотаний Seague завершено -> TextLabel of viewControllerA змінено.

введіть тут опис зображення

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.