ChatGPT解决这个技术问题 Extra ChatGPT

如何以编程方式执行 Unwind segue?

使用情节提要非常容易。您只需将操作拖到“退出”即可。但是我应该如何从我的代码中调用它?

我发现这是一个有效的问题——我自己也有过。您可以通过以下方式以编程方式执行展开转场:1. 创建手动转场(从 File's Owner 按住 ctrl-drag 到 Exit),2. 在 IB 中为其命名,然后 3. 在您的代码中执行正常的 -performSegueWithIdentifier:sender:。
不应该关闭 IMO。投票结束这个问题的用户肯定似乎没有 Obj-C / Cocoa Touch 背景。
杨:你怎么给它起名字?
我只是使用 [self dismissViewControllerAnimated:YES completion:nil];以编程方式退出。我不知道这是否正确。
sarfata:您首先通过 ctrl-drag 从 viewcontroller 到“Exit”创建一个“手动展开转场”。然后你可以在 Document Outline 中找到 segue。

V
Vadim

创建手动segue(从File's Owner 按住ctrl-drag 到Exit),在绿色EXIT 按钮下方的Left Controller Menu 中选择它。

https://i.stack.imgur.com/uWRSG.png

插入 Segue 的名称以放松。

然后,- (void)performSegueWithIdentifier:(NSString *)identifier sender:(id)sender. 使用您的 segue 标识。


1)“文件的所有者”——这不是旧术语吗?它对我来说可以控制从视图控制器到其退出图标的拖动。 2)虽然应该很明显,但 Xcode 正在 IBAction 的接口中寻找一个声明,该声明采用 UIStoryboardSegue 参数; WWDC 2012 session 407 talk 没有提到这一点,也没有粘贴该代码。没有它,我的退出图标在控制拖动到它时不会激活。 3) 在你的大红色箭头的末端,在 Action 字段中,你可以点击“去那里”箭头,这很酷!
对于像我一样仍然在实施此答案时遇到困难的任何人,我在此 repo 中整理了一个更彻底的演练和示例:github.com/bradley/iOSUnwindSegueProgramatically(不是想为自己做广告,我只是撞了头靠在墙上几个小时,看到工作设置对我有帮助。)
@bradleygriffith 你真是太棒了。感谢您的精彩演练!
@bradleygriffith 我希望你能回答这个问题,这样我也可以标记一下!您的独特贡献是确定哪个视图控制器获取什么代码。在任何地方都找不到那个。谢谢!
对于仍然对此感到困惑的人来说,关键是 IBACTION 需要在您要返回的视图控制器中,而不是您当前所在的视图控制器中。@bradleygriffith 在 GitHub 上说明了这一点,但我还没有看到在其他任何地方都提到过。这部分很关键。
S
SmileBot

这是 Objective C 和 Swift 的完整答案:

1) 在您的目标视图控制器(您想要转场的位置)中创建一个 IBAction 展开转场。实现文件中的任何位置。

// Objective C

    - (IBAction)unwindToContainerVC:(UIStoryboardSegue *)segue {

    }

// Swift

 @IBAction func unwindToContainerVC(segue: UIStoryboardSegue) {

    }

2)在源视图控制器(您要从中选择的控制器)上,⌃ + 从“活动名称”拖动以退出。您应该会在弹出窗口中看到在步骤 1 中创建的展开转场。 (如果您没有看到,请查看第一步)。从弹出窗口中选择 unwindToContainerVC: 或任何您命名的方法,以将源控制器连接到展开 IBAction。

https://i.stack.imgur.com/CJSxx.png

3)在故事板的源视图控制器的文档大纲中选择segue(它将在底部附近列出),并给它一个标识符。

https://i.stack.imgur.com/c3vvp.png

4) 使用此方法从源视图控制器调用展开转场,替换您的展开转场名称。

// 目标 C

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

// 斯威夫特

self.performSegueWithIdentifier("unwindToContainerVC", sender: self)

注意。使用 unwind 方法上 segue 参数的 sourceViewController 属性来访问源控制器上的任何公开属性。另外,请注意框架处理解除源控制器。如果您想确认这一点,请向源控制器添加一个 dealloc 方法,其中包含一条日志消息,一旦它被杀死就应该触发。如果 dealloc 没有触发,您可能有一个保留周期。


我的程序不起作用,甚至没有调用 (IBAction)unwindToContainerVC:(UIStoryboardSegue *)segue
当您正在展开的视图控制器仅存在于您的故事板中时,此解决方案不起作用,也就是在代码实现中没有自定义
@mnl 不确定您在说什么,但它适用于故事板场景或笔尖。如果您在代码中创建视图控制器场景,那么您将不会使用任何以它们的名称“返回”IB 的方法,这实际上是无效的,因为它们用于在代码和 IB 之间进行通信。这是否解决了您的评论?
您显示从 ViewControllerExitctrl+drag 的图片非常有用。谢谢!
对于 Swift 4.2 使用: self.performSegue(withIdentifier: "unwindToVC", sender: self)
p
pkamb

bradleygriffith 的回答很棒。为了简化,我采取了第 10 步并制作了屏幕截图。这是 Xcode 6 中的屏幕截图。

按住 Control 从橙色图标拖动到红色的退出图标以创建一个展开,视图中没有任何操作/按钮。

https://i.stack.imgur.com/idX9l.png

然后在侧边栏中选择 unwind segue:

https://i.stack.imgur.com/NBxT5.png

设置一个 Segue Identifier 字符串:

https://i.stack.imgur.com/OLbL5.png

从代码访问该标识符:

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

首先,展开的方法必须包含在 UIViewController 中。然后您的解决方案将起作用
你必须将 Identifier 设置为这个新的 segue!不要忘记它。
是否可以以编程方式在源视图控制器中创建“退出”连接?
J
Jack

我使用了 [self dismissViewControllerAnimated: YES completion: nil];,它会将您返回到调用 ViewController


Larry,如果您想要返回到前一个视图控制器,即呈现您现在正在退出的视图控制器的视图控制器,那么这是一种完全有效的方法。出现这个问题是因为 Xcode 4.5 中的新功能是能够从呈现顺序中的某个视图控制器“展开”到更早的视图控制器。有关详细信息,请参阅 WWDC 2012 会议 407。
V
Vishal Chaudhry

引用 Apple 关于 Unwind Segue 的技术说明中的文字:要添加只能以编程方式触发的展开 segue,请从场景的视图控制器图标中控制并拖动到其退出图标,然后从弹出菜单中为新的 segue 选择一个展开动作。

Link to Technical Note


J
Jason Crocker

Vishal Chaudhry 上面的回答对我有用。我还要补充一点,以便使用以下方法手动触发序列:

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

在 ViewController 中,您还必须在情节提要中的 ViewController 场景下选择展开转场,并在 RHS 的属性视图中确保 Indentifier 字段包含您在代码中引用的名称(上例中的“mySegueName” )。

如果省略这一步,上面的行将抛出一个序列名称未知的异常。


1
10623169

斯威夫特 4.2,Xcode 10+

对于那些想知道如何使用未通过情节提要设置的 VC 来做到这一点的人(那些通过搜索“以编程方式”+“展开转场”来解决这个问题的人)。

鉴于您无法以编程方式设置展开转场,最简单的纯编程解决方案是调用:

navigationController?.popToRootViewController(animated: true)

这会将堆栈上的所有视图控制器弹出回您的根视图控制器。

要从导航堆栈中弹出最顶层的视图控制器,请使用:

navigationController?.popViewController(animated: true)


这通常比你想要的要多 - 弹出一个就行了:[self.navigationController popViewControllerAnimated:YES];
确实,我已将其添加到我的答案中-感谢@AndyWeinstein
J
Joel Teply

向后兼容的解决方案适用于 ios6 之前的版本,适用于感兴趣的用户:

- (void)unwindToViewControllerOfClass:(Class)vcClass animated:(BOOL)animated {

    for (int i=self.navigationController.viewControllers.count - 1; i >= 0; i--) {
        UIViewController *vc = [self.navigationController.viewControllers objectAtIndex:i];
        if ([vc isKindOfClass:vcClass]) {
            [self.navigationController popToViewController:vc animated:animated];
            return;
        }
    }
}

展开 segue 的作用远不止在导航控制器堆栈中弹出回某个类。
C
Chad Parker

斯威夫特 4:

1.创建一个@IBAction,在你想放松的控制器内使用segue:

    @IBAction func unwindToVC(segue: UIStoryboardSegue) {

    }

2. 在情节提要中,从您想要从控制器符号中切换(展开)的控制器中按 ctrl+从控制器符号拖动到退出符号并选择您之前创建的方法:

https://i.stack.imgur.com/GFK4L.png

3. 现在您可以注意到在文档大纲中您有标题为“Unwind segue...”的新行。现在你应该点击这一行并打开属性检查器来设置标识符(在我的例子中是 unwindSegueIdentifier)。

https://i.stack.imgur.com/edUhH.png

4. 你快完成了!现在您需要打开您希望从中放松的视图控制器并创建一些将执行 segue 的方法。例如,您可以添加按钮,使用 @IBAction 将其与代码连接,然后在此 IBAction 中添加 perfromSegue(withIdentifier:sender:) 方法:

     @IBAction func unwindToSomeVCWithSegue(_ sender: UIButton) {
         performSegue(withIdentifier: "unwindSegueIdentifier", sender: nil)
     }

所以这就是你所要做的!


是否可以以编程方式在源视图控制器中创建“退出”连接?
J
John Verco

仅供参考:为了使@Vadim 的答案与从视图控制器中调用的手动展开序列操作一起工作,您必须放置命令:

[self performSegueWithIdentifier:(NSString*) identifier sender:(id) sender];

在被覆盖的类方法 viewDidAppear 内部,如下所示:

-(void) viewDidAppear:(BOOL) animated
{
    [super viewDidAppear: animated];

    [self performSegueWithIdentifier:@"SomeSegueIdentifier" sender:self];
}

如果您将它放在其他 ViewController 方法中,例如 viewDidLoad 或 viewWillAppear,它将被忽略。


肯定是错的。从您想要的任何地方调用 performSegueWithIdentifier。
这不会在视图加载后立即执行 unwind segue 吗?而不是在您想要时执行,例如在按下按钮后执行。
@Pahnev 是的。我不知道这个答案是如何得到任何支持的。调用 performSegueWithIdentfier 正是这样做的:执行从一个 ViewController 到另一个 ViewController 的 segue
完全错误。它会在发射时立即倒带。