我刚刚弄清楚了什么是 unwind segue 以及如何将它与这个问题的精彩答案一起使用。非常感谢。
但是,这里有一个这样的问题:
假设场景 B 中有一个按钮,它展开到场景 A,在它开始之前我想要做一些事情,比如将数据保存到数据库。我在 B.swift 中为这个按钮创建了一个动作,但它似乎直接进入场景 A 而没有采取指定的动作。
任何人都知道为什么或如何做到这一点?
谢谢你。
我刚刚弄清楚了什么是 unwind segue 以及如何将它与这个问题的精彩答案一起使用。非常感谢。
但是,这里有一个这样的问题:
假设场景 B 中有一个按钮,它展开到场景 A,在它开始之前我想要做一些事情,比如将数据保存到数据库。我在 B.swift 中为这个按钮创建了一个动作,但它似乎直接进入场景 A 而没有采取指定的动作。
任何人都知道为什么或如何做到这一点?
谢谢你。
您可以按照您描述的方式执行此操作,或者通过prepareForSegue
在您正在展开的 viewController 中使用覆盖函数:
@IBAction func actionForUnwindButton(sender: AnyObject) {
println("actionForUnwindButton");
}
或者...
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
println("prepareForSegue");
}
第一个例子就像你描述的那样。按钮连接到 unwind segue 和 Interface Builder 中的按钮操作。按钮动作将在 segue 动作之前触发。也许您没有将操作连接到界面生成器中的按钮?
第二个示例使您可以访问 segue sourceViewController
,destinationViewController
如果这也有用(您还可以在目标视图控制器的展开 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 有一个按钮,它在情节提要中连接到unwindToRed
unwind 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
prepareForSegue
和unwind
收到的消息。然而actionForUnwindButton
,由于 viewController 在 segue 期间被销毁,消息被发送到 nil。所以它没有被执行,并且日志打印
prepareForSegue
unwindToRed
在 (B) 的情况下,viewController 在方法到达之前被销毁,因此不会被触发
所以看起来你的选择是......
(a)使用带有动作的 UIButton 并展开 segue
(b)使用 触发你的动作prepareForSegue
,这将在 viewController 还活着的时候触发,并且在 segue 发生之前。
(c) 不要使用 unwind segue,只需使用按钮操作。在 action 方法中,您可以通过调用popToViewController
导航控制器来“放松”。
顺便说一句,如果你在 viewController 上实现了一个工具栏(不使用导航控制器的工具栏),结果是一样的:首先触发 segue,所以按钮操作失败。
如果您能够成功执行 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");
}
}
首先,您应该在 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];