在展开 segue 操作之前如何做某事?
How to do something before unwind segue action?
我刚刚弄清楚什么是 unwind segue 以及如何使用它以及 this 问题的出色答案。非常感谢。
但是,这里有一个这样的问题:
假设场景 B 中有一个按钮可以展开到场景 A,在它继续之前我想做一些事情,比如将数据保存到数据库中。我在B.swift中为这个按钮创建了一个动作,但它似乎没有执行指定的动作就直接进入了场景A。
任何人都知道为什么或如何做到这一点?
谢谢。
首先应该在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];
如果您能够成功执行unWind Segue。然后在 segue 发生之前调用目标 View Controller 中的方法,您可以使用 segue 对象在源 viewcontroller 中做任何您想做的事情。
- (IBAction)unwindToThisViewController:(UIStoryboardSegue *)unwindSegue
{
CustomViewController *vc = (CustomViewController*) unwindSegue.sourceViewController;
[vc performAnyMethod];
[vc saveData];
NSString *temp = vc.anyProperty;
}
如果你想在源控制器中使用你的逻辑,那么在场景 B 中实现 prepareForSegue 并在场景 B 中的 Storyboard > Left View hierarchy Panel > Exit 下设置 unWind segue Identifier。
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier] isEqualToString:@"backToSource"])
{
NSLog(@"Going Back");
}
}
您可以按照您描述的方式执行此操作,或者在您要解除的 viewController 中使用 prepareForSegue
覆盖功能:
@IBAction func actionForUnwindButton(sender: AnyObject) {
println("actionForUnwindButton");
}
或...
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
println("prepareForSegue");
}
第一个例子如你所描述。该按钮连接到 unwind segue 和 Interface Builder 中的按钮操作。按钮操作将在 segue 操作之前触发。也许您没有将操作连接到界面生成器中的按钮?
第二个示例让您可以访问 segue 的 sourceViewController
和 destinationViewController
以防万一这也很有用(您也可以在目标视图控制器的 unwind 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 unwind 动作发送到 storyboard segue
收到的所有消息和按以下顺序执行的方法:
actionForUnwindButton
prepareForSegue
unwindToRed
(B) 导航控制器工具栏中的 UIBarButtonItem
工具栏buttonItem接收touchupInside
- (1) 将 segue unwind 动作发送到 storyboard segue
- (2)(可能,然后)向 viewController 的方法
发送操作
执行顺序是
prepareForSegue
unwindToRed
actionForUnwindButton
已收到 prepareForSegue
和 unwind
条消息。然而 actionForUnwindButton
消息被发送到 nil,因为 viewController 在 segue 期间被销毁。所以它没有被执行,日志打印
prepareForSegue
unwindToRed
在 (B) 的情况下,viewController 在方法到达之前被销毁,因此不会被触发
看来你的选择是……
(a) 将 UIButton 与 action 和 unwind segue
结合使用
(b) 使用 prepareForSegue
触发您的操作,这将在 viewController 仍然存在且在 segue 发生之前触发。
(c) 不要使用 unwind segue,只需使用按钮操作。在操作方法中,您可以通过在导航控制器上调用 popToViewController
来 'unwind'。
顺便说一句,如果您在 viewController 上实现工具栏(不使用导航控制器的工具栏),结果是相同的:segue 首先被触发,因此按钮操作失败。
我刚刚弄清楚什么是 unwind segue 以及如何使用它以及 this 问题的出色答案。非常感谢。
但是,这里有一个这样的问题:
假设场景 B 中有一个按钮可以展开到场景 A,在它继续之前我想做一些事情,比如将数据保存到数据库中。我在B.swift中为这个按钮创建了一个动作,但它似乎没有执行指定的动作就直接进入了场景A。
任何人都知道为什么或如何做到这一点?
谢谢。
首先应该在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];
如果您能够成功执行unWind Segue。然后在 segue 发生之前调用目标 View Controller 中的方法,您可以使用 segue 对象在源 viewcontroller 中做任何您想做的事情。
- (IBAction)unwindToThisViewController:(UIStoryboardSegue *)unwindSegue
{
CustomViewController *vc = (CustomViewController*) unwindSegue.sourceViewController;
[vc performAnyMethod];
[vc saveData];
NSString *temp = vc.anyProperty;
}
如果你想在源控制器中使用你的逻辑,那么在场景 B 中实现 prepareForSegue 并在场景 B 中的 Storyboard > Left View hierarchy Panel > Exit 下设置 unWind segue Identifier。
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier] isEqualToString:@"backToSource"])
{
NSLog(@"Going Back");
}
}
您可以按照您描述的方式执行此操作,或者在您要解除的 viewController 中使用 prepareForSegue
覆盖功能:
@IBAction func actionForUnwindButton(sender: AnyObject) {
println("actionForUnwindButton");
}
或...
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
println("prepareForSegue");
}
第一个例子如你所描述。该按钮连接到 unwind segue 和 Interface Builder 中的按钮操作。按钮操作将在 segue 操作之前触发。也许您没有将操作连接到界面生成器中的按钮?
第二个示例让您可以访问 segue 的 sourceViewController
和 destinationViewController
以防万一这也很有用(您也可以在目标视图控制器的 unwind 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 unwind 动作发送到 storyboard segue
收到的所有消息和按以下顺序执行的方法:
actionForUnwindButton
prepareForSegue
unwindToRed
(B) 导航控制器工具栏中的 UIBarButtonItem
工具栏buttonItem接收touchupInside
- (1) 将 segue unwind 动作发送到 storyboard segue
- (2)(可能,然后)向 viewController 的方法
执行顺序是
prepareForSegue
unwindToRed
actionForUnwindButton
已收到 prepareForSegue
和 unwind
条消息。然而 actionForUnwindButton
消息被发送到 nil,因为 viewController 在 segue 期间被销毁。所以它没有被执行,日志打印
prepareForSegue
unwindToRed
在 (B) 的情况下,viewController 在方法到达之前被销毁,因此不会被触发
看来你的选择是……
(a) 将 UIButton 与 action 和 unwind segue
结合使用
(b) 使用 prepareForSegue
触发您的操作,这将在 viewController 仍然存在且在 segue 发生之前触发。
(c) 不要使用 unwind segue,只需使用按钮操作。在操作方法中,您可以通过在导航控制器上调用 popToViewController
来 'unwind'。
顺便说一句,如果您在 viewController 上实现工具栏(不使用导航控制器的工具栏),结果是相同的:segue 首先被触发,因此按钮操作失败。