【问题标题】:How to do something before unwind segue action?在展开 segue 动作之前如何做一些事情?
【发布时间】:2015-02-07 10:15:11
【问题描述】:

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

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

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

有人知道为什么或如何做到这一点吗?

谢谢。

【问题讨论】:

  • 如果您使用的是实际的展开转场(而不是 UINavigationController 中的简单后退按钮,那么 prepareForSegue 将在源视图控制器和目标视图控制器中调用 - developer.apple.com/library/ios/technotes/tn2298/_index.html#//… 您将需要如果您还没有这样做,请在情节提要中提供您的放松转场和标识符,以便在 prepareForSegue 中识别它
  • prepareForSegue 实际上只在源视图控制器中调用。

标签: ios swift unwind-segue


【解决方案1】:

您可以按照您描述的方式进行操作,或者在您要从中展开的 viewController 中使用 prepareForSegue 覆盖函数:

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

或者...

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

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

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

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

编辑

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

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 有一个按钮,它在情节提要中连接到 unwindToRed unwind segue 和 actionForUnwindButton 按钮。它还覆盖了prepareForSegue,因此我们可以记录播放顺序。

输出:

actionForUnwindButton
prepareForSegue
unwindToRed

故事板:

编辑 2

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

(A) 视图控制器中的 UIButton

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

actionForUnwindButton
prepareForSegue
unwindToRed

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

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

执行顺序是

prepareForSegue
unwindToRed
actionForUnwindButton

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

prepareForSegue
unwindToRed

在(B)的情况下,viewController在方法到达之前就被销毁了,所以不会被触发

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

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

【讨论】:

  • 非常感谢,亲爱的铸造厂。我真的希望您提出的第一个示例可以工作,因为它是最简单的方法,但事实并非如此,而且我确定按钮和操作已连接。哦,我的意思是按钮实际上是工具栏下的项目,这有关系吗?
  • @Mechanic,它在我的测试中是这样工作的。查看我的更新。
  • 尊敬的铸造厂,非常感谢您的详细解释。我是 swift 和 iOS 编码的新手,不幸的是我仍然无法正确处理。请您在这里查看我的代码link 好吗?
  • @Mechanic,查看我的更新。我认为您应该覆盖“prepareForSegue”而不是使用按钮操作。您可以使用 segue 标识符检查它是否是预期的 Segue。 或者使用按钮动作并在代码中使用'popToViewController:'方法,在按钮动作内部,而不是展开Segue。
  • @foundry 你能告诉我如何从 UIToolBar 的 UIBarButton 添加展开转场吗?
【解决方案2】:

如果您能够成功执行 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");

    }
}

【讨论】:

  • 非常感谢Irfan Gul,这种方式可能可行,但我觉得最好将这些代码放在源VC中。有什么想法吗?
【解决方案3】:

首先,你应该在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];

【讨论】:

  • 非常感谢wrUS61,这个方法真的很管用。但是,为什么我原来的方法不起作用?这是否意味着当一个按钮同时连接到展开转场和动作时,它只会响应展开转场?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多