-segueForUnwindingToViewController: fromViewController: identifier: not being called 未调用-segueForUnwindingToViewController: fromViewController: identifier:方法

23

我已经创建了一个自定义segue,用于在容器中呈现视图控制器,与苹果的模态视图控制器非常相似(我已将其实现为UIViewController子类)。

我现在正在尝试创建一个自定义返回segue,但是我无法调用方法-segueForUnwindingToViewController: fromViewController: identifier:

我还在我的容器上实现了-viewControllerForUnwindSegueAction: fromViewController: withSender:,以便我可以指向正确的视图控制器(呈现此模态视图控制器的那个),但随后应要求我的自定义返回segue的方法没有被调用。

现在,我唯一的方法是在-returned:方法中进行关闭此模态视图控制器。

是否有人成功使用自定义返回segue完成这个操作?


编辑: 更多代码和上下文

我的返回视图控制器是在Storyboard中配置的,不是通过编程方式实现的。

我在我的控制器中有这些关于返回segue的代码:

PresenterViewController.m

我在这里使用自定义方法来关闭我的自定义模态视图控制器(-dismissModalViewControllerWithCompletionBlock:)。

- (UIStoryboardSegue *)segueForUnwindingToViewController:(UIViewController *)toViewController
                                      fromViewController:(UIViewController *)fromViewController
                                              identifier:(NSString *)identifier {
    return [[MyModalUnwindSegue alloc] initWithIdentifier:identifier
                                                   source:fromViewController
                                              destination:toViewController];
}

-(IBAction)returned:(UIStoryboardSegue *)segue {
    if ([segue.identifier isEqualToString:@"InfoUnwindSegue"]) {
        [self dismissModalViewControllerWithCompletionBlock:^{}];
    }
}

MyModalViewController.m

这里我仅使用 -viewControllerForUnwindSegueAction: fromViewController: withSender: 来指向应该返回的视图控制器。

- (UIViewController *)viewControllerForUnwindSegueAction:(SEL)action 
                                      fromViewController:(UIViewController *)fromViewController 
                                              withSender:(id)sender {
    return self.myPresentingViewController;
}
我预期的行为是MyModalViewController被调用指向应该处理取消操作的视图控制器,并且在调用-returned:之前,这个视图控制器会调用-segueForUnwindingToViewController: fromViewController: identifier:方法。
目前-segueForUnwindingToViewController: fromViewController: identifier:从未被调用。
我必须说,我已经尝试过不同的配置。无论我将我的方法放在哪里以返回取消操作的转场,它都从未被调用。我读到可以对导航控制器进行子类化然后它就会被调用,但我不知道它如何适用于我的解决方案。
编辑2:附加信息
我已检查MyModalViewController是否在我想要关闭由它呈现的常规模态视图控制器时调用了他的-segueForUnwindingToViewController: fromViewController: identifier:方法。这可能是因为他是层次结构中最高级别的UIViewController。
在检查此内容后,我对UINavigationController进行了子类化,并使用这个子类来包含我的PresenterViewController。令人惊讶的是,他的-segueForUnwindingToViewController: fromViewController: identifier:方法也被调用了。
我相信只有作为容器的视图控制器才会被调用这个方法。对我来说,这有点不合理,因为它们不是唯一呈现其他视图控制器的视图控制器,它们的子视图控制器也在这样做。
对我来说,在这个子类中创建选择使用哪个segue类的逻辑是不可行的,因为这个类不知道它们的子视图控制器所做的事情。
苹果论坛暂时无法提供支持。如果有人对此有更多信息,请帮忙解决!我想缺乏关于这个问题的文档是它还不够稳定的一个良好指标。

你想查看还是关闭? - kirti Chavda
@kirtimali,我想要取消操作,因此我想要解除。 - Fábio Oliveira
你是如何为演示做初始自定义segue的? - rdelmar
@rdelmar 我已经对UIStoryboardSegue进行了子类化,并将自定义类分配给了故事板上的segue。因此,它不是以编程方式调用的。 - Fábio Oliveira
如果您有演示项目,我可以看一下。 :) - Rui Peres
显示剩余7条评论
4个回答

11

补充一下 @Jeremy 的回答,我成功地将一个模态 UIViewController 返回到包含在 UINavigationController 中的另一个 UIViewController,并且得到了我预期的效果。以下是我在 UINavigationController 子类中使用的代码:

// Pass to the top-most UIViewController on the stack.
- (UIStoryboardSegue *)segueForUnwindingToViewController:(UIViewController *)
             toViewController fromViewController:(UIViewController *)
             fromViewController identifier:(NSString *)identifier {
   UIViewController *controller = self.topViewController;
   return [controller segueForUnwindingToViewController:toViewController
                                  fromViewController:fromViewController
                                          identifier:identifier];
}

然后在 UINavigationController 内的实际 ViewController 中像往常一样实现 segueForUnwindingToViewController。


+1. 这对我非常有帮助。使用这个新的自定义导航控制器作为我的应用程序的主要导航控制器。希望没有其他问题出现... - Jonny
嗯,它真的搞乱了我应用程序周围的其他地方,所以我还原并采用了另一种解决方案。不能取消我的+1;-) 无论如何,这可能是以后有用的知识。 - Jonny
说实话,我发现上面的方法(对我来说很有效)后不久,我完全放弃了使用segue,而是全部用代码实现。这样做简单得多!一切都运行得很好! - Ben Clayton
1
是的,我也使用了代码进行解缠。我对故事板还很陌生,到目前为止概览看起来不错,但是苹果在某些方面失败了,似乎只使用由苹果制作的 GUI 完全控制应用程序的流程是不可能的。:-P - Jonny
这样做的好处是什么,相比于在UINavigationController的segueForUnwindingToViewController:实现中返回正确的segue? - Petar

5
这个方法应该在父控制器中声明。所以,如果你正在使用一个带有自定义segue的导航控制器,请子类化UINavigationController并在其上定义此方法。如果您更愿意在UINavigationController的某个子视图上定义它,则可以覆盖canPerformUnwindSegueAction:fromViewController:withSender,在UINavigationController中搜索处理程序的子项。
如果您正在使用嵌入式视图(容器视图),则请在父视图控制器中定义它。
请参见WWDC 2012 Session 407 - Adopting Storyboards in Your App的最后10分钟,了解为什么会起作用!

你能在我的描述中指出应该在哪个视图控制器中声明吗?你能找到它工作方式的解释吗?我认为 UINavigationController 应该在提供自己的 unwind segue 之前先询问其子视图控制器,因为它不是调用和创建原始 segue 的那个。你对它为什么会这样工作有不同的解释吗? - Fábio Oliveira
1
从您的描述中,我不确定百分之百。但是UINavigationController首先得到机会,因为您可能想要解开到根,并且从那里更有可能是其中一个较远的控制器。如果您只想备份一个控制器,您可能不会使用解开转场,而是可能只调用popViewController。最终,这似乎是苹果公司某些框架工程师决定的优化。 - Jeremy Massel

0

iOS开发库 关于这个方法,有一个关于iOS开发库的讨论。 - segueForUnwindingToViewController:fromViewController:identifier: 确保你的MyModalViewController是容器角色而不是容器的子控制器。如果有类似[anotherVC addChildViewController:myModalViewController];的东西,你应该把segueForUnwindingToViewController方法放在某种“AnotherVC.m”文件中。

讨论 如果您实现了一个自定义容器视图控制器,同时也使用了segue unwinding,那么您必须重写此方法。您的方法实现应该实例化并返回一个自定义segue对象,该对象执行必要的动画和其他步骤来取消展开视图控制器。


0
如果您正在使用UINavigationController并且您的segue调用了pushViewController,那么为了使用自定义的返回segue,您需要子类化UINavigationController并覆盖- (UIStoryboardSegue *)segueForUnwindingToViewController:(UIViewController *)toViewController fromViewController:(UIViewController *)fromViewController identifier:(NSString *)identifier方法。
假设我有一个名为CloseDoorSegue的自定义返回segue。我的UINavigationController子类实现可能如下:
- (UIStoryboardSegue *)segueForUnwindingToViewController:(UIViewController *)toViewController fromViewController:(UIViewController *)fromViewController identifier:(NSString *)identifier {

UIStoryboardSegue* theSegue;

if ([identifier isEqualToString:@"CloseDoor"]) {
    theSegue = [CloseBookSegue segueWithIdentifier:identifier source:fromViewController destination:toViewController performHandler:^(void){}];
} else {
    theSegue = [super segueForUnwindingToViewController:toViewController fromViewController:fromViewController identifier:identifier];
}

return theSegue;

}

在Storyboard中将您的UINavigationController子类设置为导航控制器类。只要您正确设置了“CloseDoor”作为标识符的Exit事件,就可以开始使用了。此外,请确保在取消操作中调用'popViewControllerAnimated'而不是dismiss,以保持与UINavigationControllers的推送/弹出机制一致。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接