ios6和Xcode 4.5有一个叫做“Unwind Segue”的新功能:

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

unwind segue是如何工作的,它们可以用来做什么?


当前回答

Unwind segue被用来“返回”到某个视图控制器,从这个视图控制器中,通过一些segue,你会到达“当前”视图控制器。

想象你有一个MyNavController a是它的根视图控制器。现在你使用push segue到B,现在导航控制器在它的viewControllers数组中有a和B, B是可见的。现在你用模态方式来表示C。

使用unwind segue,你现在可以从C unwind回B(即解散模态呈现的视图控制器),基本上是“撤消”模态segue。你甚至可以unwind到根视图控制器A,撤销模态segue和push segue。

Unwind segue使回溯变得容易。例如,在iOS 6之前,解散呈现的视图控制器的最佳实践是将呈现的视图控制器设置为呈现的视图控制器的委托,然后调用你的自定义委托方法,然后解散presenttedviewcontroller。听起来又麻烦又复杂?这是。这就是unwind segue很好的原因。

其他回答

至于如何在StoryBoard中使用unwind segue…

步骤1)

转到你想要unwind到的视图控制器的代码并添加这个:

objective - c

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

一定要在你的.h文件中用Obj-C声明这个方法

斯威夫特

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

步骤2)

在故事板中,到你想unwind的视图把segue从按钮拖到源视图右上方的橙色EXIT图标。

现在应该有一个选项连接到"- unwindToViewControllerNameHere"

就是这样,你的segue会在按钮被点击时unwind。

例如,如果你从viewControllerB导航到viewcontrollerera,那么在你的viewcontrollerera下面的委托就会调用,数据就会共享。

@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源视图控制器(你需要连接退出按钮到VC的退出图标,并将其连接到unwindseague:

viewControllerA的TextLabel被改变。

Unwind segue被用来“返回”到某个视图控制器,从这个视图控制器中,通过一些segue,你会到达“当前”视图控制器。

想象你有一个MyNavController a是它的根视图控制器。现在你使用push segue到B,现在导航控制器在它的viewControllers数组中有a和B, B是可见的。现在你用模态方式来表示C。

使用unwind segue,你现在可以从C unwind回B(即解散模态呈现的视图控制器),基本上是“撤消”模态segue。你甚至可以unwind到根视图控制器A,撤销模态segue和push segue。

Unwind segue使回溯变得容易。例如,在iOS 6之前,解散呈现的视图控制器的最佳实践是将呈现的视图控制器设置为呈现的视图控制器的委托,然后调用你的自定义委托方法,然后解散presenttedviewcontroller。听起来又麻烦又复杂?这是。这就是unwind segue很好的原因。

我在其他答案中没有看到的当你不知道初始segue的来源时如何处理unwind,这对我来说是更重要的用例。例如,假设你有一个帮助视图控制器(H),你从两个不同的视图控制器(a和B)中modal地显示:

A→h B→h

你如何设置unwind segue让你回到正确的视图控制器?答案是你在A和B中声明一个同名的unwind动作,例如:

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

通过这种方式,unwind会找到哪个视图控制器(A或B)发起了segue并回到它。

换句话说,unwind动作描述的是segue的来源,而不是它的去向。

简而言之

unwind segue(有时称为exit segue)可用于通过push、modal或弹窗segue导航返回(就像你从导航栏弹出导航项、关闭弹窗或解散模态呈现的视图控制器一样)。在此之上,你实际上可以通过不止一个而是一系列的push/modal/popover segue来展开。“返回”导航层次结构中的多个步骤,只需一个展开操作。

当你执行unwind segue时,你需要指定一个动作,这是你想unwind到的视图控制器的一个动作方法。

objective - c:

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

迅速:

@IBAction func unwindToThisViewController(segue: UIStoryboardSegue) {
}

当您在故事板中创建unwind segue时,将使用此操作方法的名称。而且,这个方法在unwind segue执行之前被调用。你可以从传入的UIStoryboardSegue参数中获得源视图控制器,以与发起segue的视图控制器交互(例如,获得模态视图控制器的属性值)。在这方面,该方法的功能类似于UIViewController的prepareForSegue:方法。

iOS 8更新:Unwind segue也适用于iOS 8的自适应segue,比如Show和Show Detail。

一个例子

让我们有一个带有导航控制器和三个子视图控制器的故事板:

从绿色视图控制器你可以unwind(返回)到红色视图控制器。从蓝色你可以放松到绿色或通过绿色到红色。为了启用unwind,你必须在Red和Green中添加特殊的动作方法,例如下面是Red中的动作方法:

objective - c:

@implementation RedViewController

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

@end

迅速:

@IBAction func unwindToRed(segue: UIStoryboardSegue) {
}

在添加了操作方法之后,您可以通过control-drag到Exit图标来定义故事板中的unwind segue。在这里,我们想要在按下按钮时从绿色unwind到红色:

你必须选择你想要unwind到的视图控制器中定义的动作:

您还可以从Blue(在导航堆栈中“两步远”)unwind到Red。关键是选择正确的展开动作。

在unwind segue被执行之前,action方法被调用。在这个例子中,我定义了一个从Green和Blue unwind到Red的segue。我们可以通过UIStoryboardSegue参数在动作方法中访问unwind的源:

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

迅速:

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

unwind也可以通过push/modal segue的组合来工作。例如,如果我用modal segue添加另一个黄色视图控制器,我们可以在一个步骤中从黄色unwind回红色:

从代码中展开

当你通过control-拖动某个东西到视图控制器的Exit符号来定义unwind segue时,一个新的segue会出现在文档大纲中:

选择segue并转到属性检查器显示“Identifier”属性。使用这个给你的segue一个唯一的标识符:

在此之后,unwind segue可以像其他segue一样从代码中执行:

objective - c:

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

迅速:

performSegueWithIdentifier("UnwindToRedSegueID", sender: self)