我刚刚想出了什么是一个放松的segue以及如何将它与this问题的答案一起使用。非常感谢。
然而,这是一个像这样的问题:
假设在场景B中有一个按钮可以展开到场景A的一个按钮,在它被分割之前我想要做一些事情,比如将数据保存到数据库。我在B.swift中为这个按钮创建了一个动作,但它似乎直接进入了场景A而没有采取指定的动作。
任何人都知道为什么或如何做到这一点?
谢谢。
答案 0 :(得分:21)
您可以按照描述的方式执行此操作,也可以在要解除的viewController中使用prepareForSegue
覆盖功能:
@IBAction func actionForUnwindButton(sender: AnyObject) {
println("actionForUnwindButton");
}
...或
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
println("prepareForSegue");
}
第一个例子就像你描述的那样。该按钮连接到展开segue和Interface Builder中的按钮操作。在segue动作之前将触发按钮动作。也许您没有将操作连接到界面构建器中的按钮?
第二个示例让您可以访问segue的sourceViewController
和destinationViewController
,以防万一也很有用(您也可以在unwind segue'目标视图控制器)。
如果要延迟解开segue直到按钮的本地操作完成,您可以使用self.performSegueWithIdentifier
直接从按钮操作调用segue(而不是在故事板中将其挂钩)(或遵循wrUS61的建议)
修改强>
你似乎对是否可以通过将按钮连接到展开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
展开segue和actionForUnwindButton
按钮。它还会覆盖prepareForSegue
,因此我们可以记录播放顺序。
输出:
actionForUnwindButton
prepareForSegue
unwindToRed
故事板:
编辑2
您的演示项目显示此不正在运行。不同之处在于您使用barButtonItem来触发操作,而我使用的是常规按钮。 barButtonItem失败,而常规按钮成功。我怀疑这是由于消息传递顺序的不同(接下来是猜想,但符合观察到的行为):
(A)View Controller中的UIButton
ViewController的按钮接收touchupInside
- (1)向其发出行动方法
- (2)将segue展开动作发送到故事板segue
收到的所有消息以及按此顺序执行的方法:
actionForUnwindButton
prepareForSegue
unwindToRed
(B)导航控制器工具栏中的UIBarButtonItem
工具栏buttonItem接收touchupInside
- (1)将segue展开动作发送到故事板segue
- (2)(可能,然后)将动作发送到viewController的方法
执行顺序是
prepareForSegue
unwindToRed
actionForUnwindButton
收到 prepareForSegue
和unwind
条消息。但是,当在segue期间销毁viewController时,actionForUnwindButton
消息被发送到nil。所以它没有被执行,日志打印
prepareForSegue
unwindToRed
在(B)的情况下,viewController在方法到达之前被销毁,因此不会被触发
所以看来你的选择是......
(a)使用带动作的UIButton并展开segue
(b)使用prepareForSegue
触发您的操作,这将在viewController仍处于活动状态时以及在发生segue之前触发。
(c)不要使用展开segue,只需使用按钮动作即可。在动作方法中,您可以“放松”'通过在导航控制器上调用popToViewController
。
顺便说一下,如果你在viewController上实现了一个toolBar(不使用导航控制器的工具栏),结果是一样的:首先触发segue,所以按钮动作失败。
答案 1 :(得分:3)
如果你能够成功地执行unWind Segue。然后在segue发生之前调用目标View Controller中的方法,您可以使用segue对象在源视图控制器中执行任何操作。
- (IBAction)unwindToThisViewController:(UIStoryboardSegue *)unwindSegue
{
CustomViewController *vc = (CustomViewController*) unwindSegue.sourceViewController;
[vc performAnyMethod];
[vc saveData];
NSString *temp = vc.anyProperty;
}
如果你想在源控制器中使用你的逻辑,那么在场景B中实现prepareForSegue并从Storyboard>设置unWind segue Identifier。左视图层次结构面板>在场景B中退出。
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier] isEqualToString:@"backToSource"])
{
NSLog(@"Going Back");
}
}
答案 2 :(得分: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];