Для чего нужны сегменты Unwind и как вы их используете?

iOS 6 и Xcode 4.5 имеют новую функцию, которая называется "Unwind 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

Как работают размоточные сегы и для чего они могут быть использованы?

6 ответов

Решение

В двух словах

Сегмент раскрутки (иногда называемый выходом сегмента) можно использовать для перехода назад через сегменты push, modeal или popover (как если бы вы вытолкнули элемент навигации из панели навигации, закрыли всплывающее окно или отклонили модально представленный контроллер представления). Вдобавок ко всему вы можете раскрутить не только один, но и серию сегментов push/ modal / popover, например, "вернуться назад" на несколько шагов в иерархии навигации с помощью одного действия раскрутки.

Когда вы выполняете процедуру раскрутки, вам нужно указать действие, которое является методом действия контроллера представления, к которому вы хотите раскрутиться.

Objective-C:

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

Swift:

@IBAction func unwindToThisViewController(segue: UIStoryboardSegue) {
}

Имя этого метода действия используется, когда вы создаете сценарий раскрутки в раскадровке. Кроме того, этот метод вызывается как раз перед тем, как выполняется процесс раскрутки. Вы можете получить исходный контроллер из пройденного UIStoryboardSegue параметр для взаимодействия с контроллером представления, который инициировал переход (например, для получения значений свойств модального контроллера представления). В этом отношении метод имеет функцию, аналогичную prepareForSegue: метод UIViewController,

Обновление iOS 8: сегменты Unwind также работают с адаптивными сегментами iOS 8, такими как Show and Show Detail.

Пример

Давайте рассмотрим раскадровку с контроллером навигации и тремя контроллерами дочернего представления:

Из Green View Controller вы можете развернуть (перейти назад) в Red View Controller. От Blue вы можете раскрутиться до Green или Red через Green. Чтобы включить размотку, вы должны добавить специальные методы действий в красный и зеленый, например, вот метод действия в красном:

Objective-C:

@implementation RedViewController

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

@end

Swift:

@IBAction func unwindToRed(segue: UIStoryboardSegue) {
}

После добавления метода действия вы можете определить последовательность раскрутки в раскадровке, перетащив ее на значок "Выход". Здесь мы хотим раскрутить Red с Green при нажатии кнопки:

Вы должны выбрать действие, которое определено в контроллере представления, к которому вы хотите вернуться:

Вы также можете размотаться в Red from Blue (который находится в двух шагах от стека навигации). Ключ выбирает правильное действие размотки.

Перед выполнением сеанса раскрутки вызывается метод действия. В этом примере я определил переход от Red к Green и Blue. Мы можем получить доступ к источнику раскрутки в методе действия через параметр 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")
    }
}

Разматывание также работает через комбинацию push/ модальных сегментов. Например, если бы я добавил еще один контроллер представления Yellow с модальным переходом, мы могли бы размотаться от Yellow до Red за один шаг:

Разматывание из кода

Когда вы определяете процесс размотки, перетаскивая что-либо на символ Выход из контроллера представления, в структуре документа появляется новая последовательность:

Выбор перехода и переход к инспектору атрибутов открывает свойство "Идентификатор". Используйте это, чтобы дать уникальный идентификатор вашей теме:

После этого процесс раскрутки может быть выполнен из кода, как любой другой переход:

Objective-C:

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

Swift:

performSegueWithIdentifier("UnwindToRedSegueID", sender: self)

Что касается того, как использовать раскручивать segues в StoryBoard...

Шаг 1)

Перейдите к коду для контроллера представления, к которому вы хотите развернуться, и добавьте это:

Objective-C

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

Обязательно также объявите этот метод в вашем файле.h в Obj-C

стриж

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

Шаг 2)

В раскадровке перейдите к представлению, с которого вы хотите отмотаться, и просто перетащите переход от кнопки или чего-либо еще к маленькому оранжевому значку "ВЫХОД" в верхнем правом углу исходного представления.

Теперь должна быть возможность подключиться к "- unwindToViewControllerNameHere"

Вот и все, ваш переход будет раскручиваться при нажатии кнопки.

Сегменты размотки используются для "возврата" к какому-либо контроллеру представления, из которого через несколько сегментов вы попадаете к "текущему" контроллеру представления.

Представь, что у тебя есть что-то MyNavController с A в качестве корневого контроллера. Теперь вы используете толчок, чтобы B, Теперь у контроллера навигации есть A и B в его viewControllers массив, и B виден. Теперь вы представляете C модально.

С раскручивающимися сегментами, теперь вы можете раскрутить "назад" из C в B (т.е. отклонение модально представленного контроллера представления), в основном "отмена" модального перехода. Вы можете даже полностью откатиться назад к контроллеру корневого представления A, отменяя модальный переход и толчок.

Размотка сегментов позволяет легко вернуться. Например, до iOS 6 наилучшей практикой для отклонения представленных контроллеров представления было установить контроллер представления в качестве делегата контроллера представленного представления, а затем вызвать свой пользовательский метод делегата, который затем отклоняет представленный ViewViewController. Звучит громоздко и сложно? Это было. Вот почему разматывать сегы это приятно.

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

AH
BH

Как настроить переход с обратной стороны, чтобы вернуться к правильному контроллеру просмотра? Ответ заключается в том, что вы объявляете действие по отмене в A и B с одним итем же именем, например:

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

Таким образом, раскрутка найдет тот контроллер представления (A илиB), который инициировал переход, и вернется к нему.

Другими словами, думайте о действии раскручивания, как о том, откуда идет исход, а не куда.

Swift iOS:

Шаг 1: определите этот метод в виде вашего контроллера MASTER. в который вы хотите вернуться:

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

    println("Called goToSideMenu: unwind action")

}

Шаг 2: (StoryBoard) Щелкните правой кнопкой мыши по кнопке SLAVE/CHILD EXIT и выберите "goToSideMenu". В качестве действия подключите кнопку "Button", по которой вы будете нажимать, чтобы вернуться к своему виду контроллера MASTER:

Шаг 3: Построить и запустить...

Например, если вы переходите от 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 и подключить его к размотке:

  • Unwind Seague Completed -> TextLabel для viewControllerA изменен.

Другие вопросы по тегам