Unwind segues 有什么用,你如何使用它们?

What are Unwind segues for and how do you use them?

提问人:Imre Kelényi 提问时间:9/24/2012 最后编辑:max_Imre Kelényi 更新时间:3/24/2018 访问量:239163

问:

iOS 6 和 Xcode 4.5 有一个称为“Unwind Segue”的新功能:

展开 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

放松 segues 是如何工作的,它们可以用来做什么?

iOS iOS6 UIstoryboard

评论


答:

46赞 Yang Meyer 10/2/2012 #1

展开 segue 用于“返回”到某个视图控制器,通过多个 segue,您可以从该控制器获得“当前”视图控制器。

想象一下,你有一个东西作为它的根视图控制器。现在,您可以使用推送 segue 到 .现在,导航控制器的数组中有 A 和 B,并且 B 是可见的。现在你以模式呈现。MyNavControllerABviewControllersC

使用展开 segue,您现在可以从 to “返回”(即关闭模态呈现的视图控制器),基本上“撤消”模态 segue。你甚至可以一直放松到根视图控制器,撤消模态 segue 和推送 segue。CBA

放松 segues 可以很容易地回溯。例如,在 iOS 6 之前,关闭呈现的视图控制器的最佳做法是将呈现视图控制器设置为呈现的视图控制器的委托,然后调用自定义委托方法,然后关闭 presentedViewController。听起来很繁琐和复杂?确实如此。这就是为什么放松 segues 很好。

评论

7赞 mxcl 9/26/2013
您可以从提供的控制器进行调用。您不必委派它。当然,如果你需要传回数据,那么你需要委托或其他一些方法。dismissViewController:animated
3赞 Chris Nolet 7/9/2014
虽然你可以从呈现的控制器调用,但正如 Yang 所提到的,“最佳实践”实际上是在呈现控制器上调用一个委托方法来为你做到这一点。dismissViewController:animated:
169赞 Travis M. 10/12/2012 #2

至于如何在 StoryBoard 中使用展开 segues......

步骤1)

转到要展开的视图控制器代码,并添加以下内容:

Objective-C语言

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

请务必在 Obj-C 的 .h 文件中声明此方法

迅速

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

步骤2)

在故事板中,转到要从中展开的视图,只需将按钮或其他任何内容拖动到源视图右上角的橙色小“退出”图标即可。

enter image description here

现在应该有一个选项可以连接到“- unwindToViewControllerNameHere”

就是这样,当您的按钮被点击时,您的 segue 就会放松。

评论

5赞 Steven Fisher 6/22/2013
我发现在 Xcode 4.5 及更早版本中,有必要在标头中声明 IBAction。我不知道这是否仍然正确。
2赞 Van Du Tran 1/28/2015
有没有办法在没有故事板的情况下完成第 2 步,即以编程方式?我的故事板(界面构建器)搞砸了,它没有显示展开 segues(xcode 错误)。
1289赞 Imre Kelényi 4/6/2013 #3

简而言之

展开 segue(有时称为退出 segue)可用于在推送、模式或弹出框 segue 之间导航(就像您从导航栏中弹出导航项、关闭弹出框或关闭模式呈现的视图控制器一样)。最重要的是,您实际上不仅可以通过一个步骤,还可以通过一系列推送/模态/弹出窗口来放松,例如,通过一个展开操作“返回”导航层次结构中的多个步骤。

在执行展开 segue 时,需要指定一个操作,该操作是要展开到的视图控制器的操作方法。

目标-C:

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

迅速:

@IBAction func unwindToThisViewController(segue: UIStoryboardSegue) {
}

在情节提要中创建展开 segue 时,将使用此操作方法的名称。此外,此方法在执行放卷 segue 之前调用。您可以从传递的参数中获取源视图控制器,以便与启动 segue 的视图控制器进行交互(例如,获取模式视图控制器的属性值)。在这方面,该方法具有与 的方法类似的功能。UIStoryboardSegueprepareForSegue:UIViewController

iOS 8更新:Unwind segue 还适用于 iOS 8 的自适应 segues,例如“显示”和“显示详细信息”。

一个例子

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

enter image description here

从 Green View Controller 中,您可以展开(导航回)到 Red View Controller。从蓝色到绿色,你可以放松到绿色,或者通过绿色放松到红色。要启用放卷,您必须将特殊操作方法添加到红色和绿色中,例如,这是红色的操作方法:

目标-C:

@implementation RedViewController

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

@end

迅速:

@IBAction func unwindToRed(segue: UIStoryboardSegue) {
}

添加操作方法后,可以通过按住控件将 Ctrl 拖动到“退出”图标,在情节提要中定义展开 segue。在这里,我们希望在按下按钮时从绿色放松到红色:

enter image description here

您必须选择要展开到的视图控制器中定义的操作:

enter image description here

您还可以从蓝色(在导航堆栈中“两步之遥”)放松到红色。关键是选择正确的放卷动作。

在执行放卷之前,将调用 action 方法。在示例中,我定义了一个从绿色和蓝色到红色的展开序列。我们可以通过 UIStoryboardSegue 参数在 action 方法中访问展开的源:

目标-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")
    }
}

展开也通过推/模态 segue 的组合来工作。例如,如果我添加了另一个带有模态 segue 的 Yellow 视图控制器,我们只需一步即可从 Yellow 一直放松到 Red:

enter image description here

从代码中解脱出来

当您通过将某些内容拖动到视图控制器的“退出”符号来定义展开 segue 时,文档大纲中会出现一个新的 segue:

enter image description here

选择 segue 并转到 Attributes Inspector 将显示 “Identifier” 属性。使用它为您的 segue 提供唯一标识符:

enter image description here

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

目标-C:

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

迅速:

performSegueWithIdentifier("UnwindToRedSegueID", sender: self)

评论

13赞 Sam Spencer 7/3/2013
+1 很好的答案。它们听起来真的很好,但方法不能像或实现同样的事情吗?dismissViewControllerAnimated:completion:popViewControllerAnimated:
33赞 Imre Kelényi 7/5/2013
当然可以。但是,如果您使用的是故事板,展开 segue 通常可以用更少的代码实现相同的目的。实际上,现在您可以关闭以模式呈现的视图控制器,而无需编写任何代码。当然,在很多情况下,从代码中关闭控制器是正确的做法。
7赞 Kyle C 8/29/2013
请确保将操作方法添加到头文件中,否则 Storyboard 将不知道。
18赞 honus 9/24/2013
与 or 相比,另一个优点是,您添加到要展开到的视图控制器的方法被调用,因此您可以轻松地知道所呈现的视图控制器已完成,而不必使呈现的视图控制器成为所呈现的视图控制器的委托。dismissViewControllerAnimated:completion:popViewControllerAnimated:
8赞 John Ballinger 1/23/2014
我可以建议稍微编辑一下吗?在 RedViewController.m 中放置 - (IBAction)unwindTRed:(UIStoryboardSegue *)unwindSegue 并不“明显”清楚,反过来,这在任何故事板的“任何”绿色退出按钮中普遍可用。很棒的答案,现在我将将其用于其他问题。谢谢!
24赞 Vinod Joshi 11/21/2014 #4

Swift iOS版:

第 1 步:在 MASTER 控制器视图中定义此方法。您要返回的:

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

    println("Called goToSideMenu: unwind action")

}

第 2 步:(故事板)右键单击您的 SLAVE/CHILD EXIT 按钮并选择“goToSideMenu”作为连接按钮的操作,您将单击该按钮返回您的 MASTER 控制器视图:

enter image description here第 3 步:构建并运行...

37赞 shawkinaw 12/16/2015 #5

我在这里的其他答案中没有看到提到的是,当你不知道最初的 segue 起源于哪里时,你如何处理解仓,这对我来说是一个更重要的用例。例如,假设您有一个帮助视图控制器 (H),您可以从两个不同的视图控制器(AB)以模式方式显示该控制器:

A → H B → H

如何设置展开 segue 以便返回到正确的视图控制器?答案是,您在 AB声明了同名的平仓操作,例如:

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

这样,展开将找到启动 segue 的视图控制器(AB)并返回它。

换句话说,将展开操作视为描述segue的来源,而不是它要去的地方。

评论

2赞 Madhu 3/12/2016
感谢您提供此信息,我一直在寻找这个。
2赞 Amr Angry 5/19/2016
提到这个信息真的很棒,因为我已经实施了解决方案,在我在这里得到你的提示之前,什么也没发生,非常感谢你的支持
0赞 Dominique Vial 12/14/2016
这是一个很好的信息!谢谢!
1赞 Sunil M. 12/22/2017 #6

例如,如果从 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"
            }
            
        }

}
  • Unwind Seague Source View 控制器 ( 您需要将退出按钮连接到 VC 的退出图标并将其连接到 unwindseague:

enter image description here

  • Unwind Seague Completed -> viewControllerA 的 TextLabel 已更改。

enter image description here