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是如何工作的,它们可以用来做什么?


当前回答

我在其他答案中没有看到的当你不知道初始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的来源,而不是它的去向。

其他回答

至于如何在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。

我在其他答案中没有看到的当你不知道初始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的来源,而不是它的去向。

例如,如果你从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被改变。

斯威夫特iOS:

步骤1:在MASTER控制器视图中定义这个方法。其中你想要返回:

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

    println("Called goToSideMenu: unwind action")

}

(StoryBoard)右键单击SLAVE/CHILD EXIT按钮,选择“gotosidemmenu”作为连接按钮,单击该按钮将返回到主控制器视图:

步骤3:构建并运行…

简而言之

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)