iOS 8 和 iOS 9 的自定义 Unwind Segue

Custom Unwind Segue for iOS 8 and iOS 9

我的问题是,如何让以下自定义展开转场在 iOS 9 之前版本的设备以及 运行 设备上运行iOS9?

我有一个显示视图控制器的 Custom Segue,然后有一个相应的 Custom Unwind Segue。这段代码在 iOS 8 中运行良好,通过创建 UIStoryboardSegue 的子类并实现 perform 方法来实现。然后我在自定义导航控制器中覆盖以下方法:

- (UIStoryboardSegue *) segueForUnwindingToViewController:    (UIViewController *)toViewController fromViewController:(UIViewController *)fromViewController identifier:(NSString *)identifier
{
    UIStoryboardSegue *segue;
    if([fromViewController isKindOfClass:[MyViewController class]]){
        segue = [[CustomSegue alloc] initWithIdentifier:identifier source:fromViewController destination:toViewController]; //Custom Unwind Segue
    }
    else{
        UIStoryboardSegue *unwindSegue = [super segueForUnwindingToViewController:toViewController fromViewController:fromViewController identifier:identifier]; //Normal Unwind Segue
        segue = unwindSegue;
    }
    return segue;
}

在 iOS 9 中,segueForUnwindingToViewController 已弃用。它仍然适用于 MyViewController CustomSegue;然而,默认的 unwind segue 不再适用于任何其他 unwind segue。虽然调用 super returns 上的方法是一个展开转场,但转场从未发生,视图控制器永远不会弹出,用户也永远无法返回到上一个屏幕。所以要明确一点,如果我使用常规的 show segue,相应的 unwind segue 会调用已弃用的方法,该方法会调用 super 上的方法,但不起作用。

我在 Storyboard 上观看了 WWDC 演讲,我在 iOS 9 中解决了这个问题,方法是 a) 不再在我的自定义 Navigation Controller 中覆盖此方法,以及 b) 进入 Storyboard,单击自定义转场,然后输入 CustomSegue 作为转场 Class。不幸的是,由于我的目标是 iOS 7,所以我收到警告 "Only Custom segues support class names prior to iOS 9",并且自定义展开转场现在不适用于 iOS 7 或 iOS 8!

经过反复试验,我找到了解决方法。我注意到当您覆盖 segueForUnwindingToViewController 时,不再调用 unwindForSegue:towardsViewController,这就是问题所在。仅供参考,Apple 在 segueForUnwindingToViewController 的 UIViewController 中的注释说:

Deprecated. Returns a segue that will unwind from the source to destination view controller via the unwindForSegue:towardViewController: method. When performing an unwind segue defined in a storyboard, if any view controller along the unwind path has overridden this method and returns non-nil, the runtime will use that segue object instead of constructing an instance of the class specified in Interface Builder.

语句中粗体部分似乎没有实现,即如果您覆盖此方法但 return nil,unwindForSegue:towardViewController 仍未被调用并且不会发生 segue。

为了解决这个问题,我能够在自定义导航控制器中编辑 segueForUnwindingToViewController

- (UIStoryboardSegue *)segueForUnwindingToViewController:(UIViewController *)toViewController fromViewController:(UIViewController *)fromViewController identifier:(NSString *)identifier
{
    UIStoryboardSegue *segue;
    if([fromViewController isKindOfClass:[MyViewController class]]){
        segue = [[CustomSegue alloc] initWithIdentifier:identifier source:fromViewController destination:toViewController]; //Custom Unwind Segue
    }
    else{
        if([[UIDevice currentDevice].systemVersion floatValue] < 9.0){
            return [super segueForUnwindingToViewController:toViewController fromViewController:fromViewController identifier:identifier]; //Normal Unwind Segue
        }
        else{
            [super unwindForSegue:segue towardsViewController:toViewController];
            return nil;
        }
    }
    return segue;
}

更新: 调用 [super segueForUnwindingToViewController:toViewController fromViewController:fromViewController identifier:identifier]; 似乎仍然适用于模态展开转场。我描述的问题似乎发生在 show segues 上。因此,如果您的设备运行的版本低于 9.0,或者如果 segue 是模态的,您仍然应该调用旧方法。如果在 segue 为模态时调用 [super unwindForSegue:segue towardsViewController:toViewController];,则 segue 不会 work/occur.

我稍微修改了你的代码。
我不必考虑是推送还是模态。
好像还不错。

- (UIStoryboardSegue *)segueForUnwindingToViewController:(UIViewController *)toViewController fromViewController:(UIViewController *)fromViewController identifier:(NSString *)identifier
{
    UIStoryboardSegue *segue;
    if ([fromViewController isKindOfClass:[MyViewController class]]) {
        segue = [[CustomSegue alloc] initWithIdentifier:identifier source:fromViewController destination:toViewController]; //Custom Unwind Segue
    }
    else {
        if ([super respondsToSelector:@selector(unwindForSegue:towardsViewController:)]) {
            [super unwindForSegue:segue towardsViewController:toViewController];
        }
        segue = [super segueForUnwindingToViewController:toViewController fromViewController:fromViewController identifier:identifier];
    }

    return segue;
}