17

我刚刚弄清楚了什么是 unwind segue 以及如何将它与这个问题的精彩答案一起使用。非常感谢。

但是,这里有一个这样的问题:

假设场景 B 中有一个按钮,它展开到场景 A,在它开始之前我想要做一些事情,比如将数据保存到数据库。我在 B.swift 中为这个按钮创建了一个动作,但它似乎直接进入场景 A 而没有采取指定的动作。

任何人都知道为什么或如何做到这一点?

谢谢你。

4

3 回答 3

22

您可以按照您描述的方式执行此操作,或者通过prepareForSegue在您正在展开的 viewController 中使用覆盖函数:

@IBAction func actionForUnwindButton(sender: AnyObject) {
    println("actionForUnwindButton");
}

或者...

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    println("prepareForSegue");
}

第一个例子就像你描述的那样。按钮连接到 unwind segue 和 Interface Builder 中的按钮操作。按钮动作将在 segue 动作之前触发。也许您没有将操作连接到界面生成器中的按钮?

第二个示例使您可以访问 segue sourceViewControllerdestinationViewController如果这也有用(您还可以在目标视图控制器的展开 segue 函数中获得这些)。

如果您想延迟展开 segue 直到按钮的本地操作完成,您可以使用self.performSegueWithIdentifier(或遵循 wrUS61 的建议)直接从按钮操作(而不是将其连接到情节提要中)调用 segue

编辑

您似乎怀疑是否可以通过将按钮连接到展开segue和按钮操作来完成此操作。我已经建立了一个像这样的小测试项目:

class BlueViewController: UIViewController {

    @IBAction func actionForUnwindButton(sender: AnyObject) {
        println("actionForUnwindButton");
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        println("prepareForSegue");
    }
}


class RedViewController: UIViewController {

    @IBAction func unwindToRed(sender: UIStoryboardSegue) {
        println("unwindToRed");
    }
}

BlueViewController 有一个按钮,它在情节提要中连接到unwindToRedunwind segue 和actionForUnwindButton按钮。它也会覆盖prepareForSegue,因此我们可以记录播放顺序。

输出:

actionForUnwindButton
prepareForSegue
unwindToRed

故事板:

在此处输入图像描述

编辑 2

您的演示项目显示这不起作用。不同之处在于您使用的是 barButtonItem 来触发操作,而我使用的是常规按钮。barButtonItem 失败,而常规按钮成功。我怀疑这是由于消息传递顺序的不同(以下是推测,但符合观察到的行为):

(A) 视图控制器中的 UIButton

ViewController 的按钮接收 touchupInside
- (1) 向其方法发送动作
- (2) 将 segue unwind 动作发送到故事板 segue
所有收到的消息,并按以下顺序执行方法:

actionForUnwindButton
prepareForSegue
unwindToRed

(B) 导航控制器工具栏中的 UIBarButtonItem

工具栏 buttonItem 接收 touchupInside
- (1) 将 segue unwind 动作发送到故事板 segue
- (2) (可能) 将动作发送到 viewController 的方法

执行顺序是

prepareForSegue
unwindToRed
actionForUnwindButton

prepareForSegueunwind收到的消息。然而actionForUnwindButton,由于 viewController 在 segue 期间被销毁,消息被发送到 nil。所以它没有被执行,并且日志打印

prepareForSegue
unwindToRed

在 (B) 的情况下,viewController 在方法到达之前被销毁,因此不会被触发

所以看起来你的选择是......
(a)使用带有动作的 UIButton 并展开 segue
(b)使用 触发你的动作prepareForSegue,这将在 viewController 还活着的时候触发,并且在 segue 发生之前。
(c) 不要使用 unwind segue,只需使用按钮操作。在 action 方法中,您可以通过调用popToViewController导航控制器来“放松”。

顺便说一句,如果你在 viewController 上实现了一个工具栏(不使用导航控制器的工具栏),结果是一样的:首先触发 segue,所以按钮操作失败。

在此处输入图像描述

于 2015-02-07T11:25:36.543 回答
3

如果您能够成功执行 unWind Segue。然后在 segue 发生之前调用目标视图控制器中的方法,您可以使用 segue 对象在源视图控制器中做任何您想做的事情。

- (IBAction)unwindToThisViewController:(UIStoryboardSegue *)unwindSegue
{
  CustomViewController *vc = (CustomViewController*) unwindSegue.sourceViewController;
  [vc performAnyMethod];
  [vc saveData];
  NSString *temp = vc.anyProperty;

}

如果您希望源控制器中的逻辑,则在场景 B 中实现 prepareForSegue 并从情节提要 > 左视图层次面板 > 在场景 B 中的退出下设置 unWind segue 标识符。

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if([[segue identifier] isEqualToString:@"backToSource"])
    {
        NSLog(@"Going Back");

    }
}
于 2015-02-07T10:37:40.710 回答
2

首先,您应该在 prepareForSegue 方法中调用发送数据函数。

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if([[segue identifier] isEqualToString:@"UnwindIdentifier"]) {
        // send data
    }
}

如果您不想让 unwind segue 在从服务器获得响应之前发生,您应该覆盖

- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender

方法和return NO;。然后,您可以通过调用以下方式在获得服务器响应时手动执行 segue:

[self performSegueWithIdentifier:@"UnwindIdentifier" sender:sender];
于 2015-02-07T10:36:24.897 回答