viewWillAppear使用transitionFromView使用自定义segue动画调用两次

时间:2012-10-17 18:46:40

标签: objective-c ios ios6 segue uistoryboardsegue

我正在寻找一个segue,用另一个视图控制器使用curl up动画替换窗口的根视图控制器。 我的想法是,在使用卷曲动画转换(SplashViewController)到下一个performSegueWithIdentifier:之前,我会显示LoginViewController几秒钟。

我创建了一个名为UIStoryboardSegue的自定义AnimatedSegue类。以下是重写的perform方法的代码:

- (void)perform
{
  UIViewController *source = self.sourceViewController;
  UIViewController *destination = self.destinationViewController;

  UIWindow *window = source.view.window;

  [UIView transitionFromView:source.view
                      toView:destination.view
                    duration:1.0
                     options:UIViewAnimationOptionTransitionCurlUp
                  completion:^(BOOL finished) {
                    [window setRootViewController:destination];
                  }];
}

除了在iOS 6中(显然不是在iOS 5中)之外,viewWillAppear:方法在destination视图控制器上被调用了两次。 它似乎是在过渡期间第一次被称为第二次被称为[window setRootViewController:destination];

请注意,我不想使用导航控制器。转换结束后,SplashViewController将被取消分配(按预期方式)。

关于如何解决问题的任何想法?

3 个答案:

答案 0 :(得分:10)

回答我自己的问题,以防它可以帮助别人......

我最终使用 Core Animation CATransition类来创建segue的动画,而不是UIView的动画方法。

以下是我的新perform方法的样子:

- (void)perform
{
  UIViewController *source = self.sourceViewController;
  UIWindow *window = source.view.window;

  CATransition *transition = [CATransition animation];
  [transition setDuration:1.0];
  [transition setDelegate:self];
  [transition setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
  [transition setType:@"pageCurl"];
  [transition setSubtype:kCATransitionFromBottom];

  [window.layer addAnimation:transition forKey:kCATransition];
  [window setRootViewController:self.destinationViewController];
}

答案 1 :(得分:2)

我可能会以不同的方式使用2个视图和一个控制器,而不是2个带有自定义segue的控制器。在您的故事板中,只需要一个控制器的空白视图,并添加两个xib文件(视图类型)以及启动视图和主视图。启动视图将作为viewDidLoad中控制器视图的子视图添加,然后使用您执行的相同方法切换出来:

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.splashView = [[NSBundle mainBundle] loadNibNamed:@"SplashView" owner:self options:nil].lastObject;
    [self.view addSubview:self.splashView];
    [self performSelector:@selector(removeSplash) withObject:nil afterDelay:2];
}

-(void)removeSplash {
    self.mainView = [[NSBundle mainBundle] loadNibNamed:@"MainView" owner:self options:nil].lastObject;
    [UIView transitionFromView: self.splashView toView:self.mainView duration:.6 options:UIViewAnimationOptionTransitionCurlUp
                    completion:nil];
}

答案 2 :(得分:1)

如果你真的,真的想要使用transitionFromView:我唯一可以找到的工作就是创建一个源视图控制器的屏幕截图,并为其设置动画。

- (void)perform
{
    UIViewController *source = self.sourceViewController;
    UIViewController *destination = self.destinationViewController;

    // Create screenshot for animation
    UIGraphicsBeginImageContextWithOptions(source.view.bounds.size, NO, 0.0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    [source.view.layer renderInContext:context];
    UIImageView *screenShot = [[UIImageView alloc] initWithImage:UIGraphicsGetImageFromCurrentImageContext()];
    UIGraphicsEndImageContext();

    // Put destination view controller and screen shot in place
    UIWindow *window = source.view.window;
    window.rootViewController = destination;
    [window addSubview:screenShot];

    [UIView transitionFromView:screenShot
                        toView:destination.view
                      duration:1.0
                       options:UIViewAnimationOptionTransitionCurlUp
                    completion:^(BOOL finished) {
                    }];
}

viewWillAppear:及其同类只会按预期调用一次。