23

I have created a custom segue that presents a view controller inside a container that is very similar with Apple's own modal view controllers (I've implemented it as a UIViewController subclass).

I'm now trying to create a custom unwind segue but there's no way I can get the method -segueForUnwindingToViewController: fromViewController: identifier: to be called.

I've also implemented -viewControllerForUnwindSegueAction: fromViewController: withSender: on my container so I can point to the correct view controller (the one that presented this modal) but then the method that should be asked for my custom unwind segue doesn't get called anywhere.

Right now, the only way for me to dismiss this modal is to do it on the -returned: method.

Did anyone could successfully do this with a custom unwind segue?


EDIT: A little bit more code and context

My unwind view controller is configured in the storyboard, not programatically.

I have these pieces of code related to the unwind segues in my controllers:

PresenterViewController.m

I'm using a custom method to dismiss my custom modals here (-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

Here I only use -viewControllerForUnwindSegueAction: fromViewController: withSender: to point to the view controller that I should be unwind to.

- (UIViewController *)viewControllerForUnwindSegueAction:(SEL)action 
                                      fromViewController:(UIViewController *)fromViewController 
                                              withSender:(id)sender {
    return self.myPresentingViewController;
}

The behavior I was expecting was that MyModalViewController was called to point to the view controller that should handle the unwinding and then this view controller had his -segueForUnwindingToViewController: fromViewController: identifier: method called before -returned: gets called.

Right now -segueForUnwindingToViewController: fromViewController: identifier: never gets called.

I must also say that I already tried different configurations. Everywhere I put my method to return the unwind segue it never gets called. I've read that I can subclass a navigation controller and then it gets called but I don't know how it would fit in my solution.


EDIT 2: Additional info

I've checked that MyModalViewController has his -segueForUnwindingToViewController: fromViewController: identifier: method called when I want to dismiss a regular modal view controller presented by it. This may be because he's the top most UIViewController in the hierarchy.

After checking this I've subclassed UINavigationController and used this subclass instead to contain my PresenterViewController. I was quite surprised to notice that his -segueForUnwindingToViewController: fromViewController: identifier: method is called as well.

I believe that only view controllers that serve as containers have this method called. That's something that makes little sense for me as they are not the only ones presenting other view controllers, their children are also doing so.

It's not OK for me to create logic in this subclass to choose which segue class to use as this class has no knowledge of what their children did.

Apple forums are down for the moment so no way to get their support right now. If anyone has any more info on how this works please help! I guess the lack of documentation for this is a good indicator of how unstable this still is.

4

4 回答 4

11

为了补充@Jeremy 的答案,我在 UINavigationController 子类中使用以下内容从模态 UIViewController 到 UINavigationController 中包含的 UIViewController 正常工作(即我期望的方式)。

// 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。

于 2013-11-13T14:26:18.997 回答
5

此方法应在父控制器上声明。因此,如果您正在使用带有自定义 segue 的导航控制器,请继承 UINavigationController 并在其上定义此方法。如果您希望在 UINavigationController 的子视图之一上定义它,您可以覆盖 UINavigationController 上的 canPerformUnwindSegueAction:fromViewController:withSender 以使其在子视图中搜索处理程序。

如果您使用的是嵌入式视图(容器视图),则在父视图控制器上定义它。

请参阅 WWDC 2012 Session 407 的最后 10 分钟 - 在您的应用程序中采用 Storyboard 以了解其工作原理!

于 2013-08-12T20:48:23.970 回答
0

如果您使用的是 UINavigationController 并且您的 segue 正在调用pushViewController,那么为了使用自定义展开 segue,您需要继承 UINavigationController 和 override - (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;

}

将您的 UINavigationController 子类设置为故事板中的导航控制器类。如果您已使用“CloseDoor”作为标识符正确设置了 Exit 事件,那么您应该很高兴。还要确保在你的 unwind segue 中调用 'popViewControllerAnimated' 而不是关闭,以与 UINavigationControllers 推送/弹出机制保持一致。

于 2015-02-25T20:26:31.907 回答
0

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

讨论 如果你实现了一个自定义容器视图控制器,它也使用 segue 展开,你必须重写这个方法。您的方法实现应该实例化并返回一个自定义 segue 对象,该对象执行展开视图控制器所需的任何动画和其他步骤。

于 2015-06-22T17:18:33.377 回答