使用自定义segue执行自定义过渡的正确方法 - 没有副作用

时间:2014-02-05 15:31:40

标签: ios objective-c uiviewcontroller uistoryboardsegue transitions

考虑到网上有许多教程可以向您展示如何使用自定义UIStoryboardSegue来在视图控制器之间进行自定义动画过渡,我想知道是否有“正确”的方法来实现它。

我应该注意,我正在考虑如何以模态方式进行此操作,而不是使用导航控制器。

我意识到有一些新方法专门用于动画iOS 7中视图控制器之间的过渡,但如果我需要定位iOS 6呢?或者如果在iOS 7的方式中存在缺点(有问题,请参阅我的问题here),使用自定义segue方法可以轻松解决该问题。

问题是大多数教程都是这样的:

在自定义segue执行方法中,首先将一个视图控制器的视图添加到另一个视图控制器视图,然后执行所需的任何自定义动画。然后在动画结束后,您将调用(如果以模态方式呈现或解除)

[sourceViewController presentViewController:destinationViewController animated:NO completion:NULL]

这种方法的问题是viewWillAppear:和viewDidAppear:被调用两次,viewWillDisappear等被调用一次,所有这些都在过渡动画中。这不是理想的行为。

有没有正确的方法可以实现这一目标?有关此问题的进一步讨论,请参阅Phil Beauvoir在其博客上发布的tutorial,并向下滚动到评论。

此外,我发现其他人已经提出了几乎同样的问题,但是我仍然问我的,因为我的研究发现了一些在他的question中没有解决的问题。此外,他的问题给出的答案并没有解决这个问题,而是提供了另一种方法,即iOS 7方法,它不能满足我的特殊需求。

1 个答案:

答案 0 :(得分:1)

我认为没有一种理想的方法可以做到这一点。正如您对其他问题的评论中提到的那样,Apple没有让我们访问复制其模态转换所需的所有内容。具体来说,presentViewController和presentsViewController属性是只读的,因此我们无法设置它们。对视图回调的多余调用的问题在于调用presentViewController:animated:completion:在转换的完成块中,因此消除该调用解决了大部分特定问题。

我最接近复制Apple的模态转换(但从顶部开始)是这样做的:

#import "CoverVerticalDown.h"
#import "ViewController.h"
#import "BlueViewController.h"

@implementation CoverVerticalDown

-(void)perform {
    ViewController *s = self.sourceViewController;
    BlueViewController *d = self.destinationViewController;
    [s.view.window addSubview: d.view];
    d.view.frame = CGRectMake(0, -480, 320, 480);
    [UIView animateWithDuration:.5 animations:^{
        d.view.frame = CGRectMake(0, 0, 320, 480);
    } completion:^(BOOL finished) {
        NSLog(@"Starting completion block of transition");
        [s.view removeFromSuperview];
        s.rdPresentedViewController = d;
        d.rdPresentingViewcontroller = s;
    }];
}

这确实使最终状态与模态转换相同 - 也就是说,窗口只有一个视图(新视图),窗口的rootViewController仍然是源视图控制器,并且没有子视图控制器。但是正如你所看到的,要做到这一点,segue需要“知道”(通过导入)源和目标控制器类是什么,所以我可以设置他们的自定义rdPresentedViewController和rdPresentingViewController属性。至少第一个需要设置,以便保留所呈现的控制器(这可以在prepareForSegue中完成,我想,所以也许你不必在segue代码中有这个)。回调序列与标准模态有一个区别 - 源控制器的viewWillDisappear方法直到完成块才被调用,而在正常模态的过渡期间调用它。这种方法也没有考虑旋转,所以如果你旋转设备然后进行转换,它将从侧面进入。要解决这个问题,你必须自己进行旋转变换。