为什么我的UIViewController被加载两次? IOS 7

时间:2014-09-09 07:59:56

标签: objective-c animation ios7 presentmodalviewcontroller uiviewanimationtransition

我使用自定义动画展示我的自定义UIViewController(称为" temp")。 UIVC被调用:

[temp setModalPresentationStyle:UIModalPresentationCustom];
temp.transitioningDelegate = self;
[temp.view setHidden:YES];
[self presentViewController:temp animated:YES completion:nil];

我的自定义动画从屏幕的右上角位置以模态方式呈现视图。它被隐藏呈现,因此用户无法看到动画。在它到达SCREEN_HEIGHT(768)位置后,它被设置为可见,并且从中到下呈现从上到下的动画(移动)。目标是从上到下呈现视图并从上到下将其关闭(如电影场景)。这段代码不合格:

- (void)animateTransition:(id)transitionContext
{
    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    NSLog(@" fromViewController %@ ",fromViewController);
    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    NSLog(@" toViewController %@ ",toViewController);
    UIView *containerView = [transitionContext containerView];
    if (self.presenting)
    {
        // set starting rect for animation toViewController.view.frame = [self rectForDismissedState:transitionContext];
        [containerView addSubview:toViewController.view];
        [UIView animateWithDuration:0.5
                         animations:^{

                             toViewController.view.frame = CGRectMake(-self.customSize.width, self.yValue, self.customSize.width, self.customSize.height);
                         }
                         completion:^(BOOL finished)
         {
             //HERE IS THE PROBLEM!!!
             [toViewController.view setHidden:NO];
             [UIView animateWithDuration:[self transitionDuration:transitionContext]
                              animations:^{
                                  CGRect variable = [self rectForPresentedState:transitionContext];
                                  CGRect fitToCurrentScreenResolution = CGRectMake(0, 0, variable.size.width, variable.size.height);
                                  toViewController.view.frame = fitToCurrentScreenResolution;

                              }
                              completion:^(BOOL finished)
              {
                  [transitionContext completeTransition:YES];
              }];
        }];
    }
    else
    {
        [UIView animateWithDuration:[self transitionDuration:transitionContext]
                         animations:^{
                             fromViewController.view.frame = [self rectForDismissedState:transitionContext];
                         }
                         completion:^(BOOL finished)
         {
             [transitionContext completeTransition:YES];
             [fromViewController.view removeFromSuperview];
         }
         ];
    }
}

这是解决方案:

- (void)animateTransition:(id)transitionContext
{
    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    NSLog(@" fromViewController %@ ",fromViewController);
    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    NSLog(@" toViewController %@ ",toViewController);
    UIView *containerView = [transitionContext containerView];
    if (self.presenting)
    {
        // set starting rect for animation toViewController.view.frame = [self rectForDismissedState:transitionContext];
        [containerView addSubview:toViewController.view];
        [UIView animateWithDuration:0.5
                         animations:^{

                             toViewController.view.frame = CGRectMake(-self.customSize.width, self.yValue, self.customSize.width, self.customSize.height);
                         }
         ];

        [toViewController.view setHidden:NO];
        [UIView animateWithDuration:[self transitionDuration:transitionContext]
                         animations:^{
                             CGRect variable = [self rectForPresentedState:transitionContext];
                             CGRect fitToCurrentScreenResolution = CGRectMake(0, 0, variable.size.width, variable.size.height);
                             toViewController.view.frame = fitToCurrentScreenResolution;

                         }
                         completion:^(BOOL finished)
         {
             [transitionContext completeTransition:YES];
         }];
    }
    else
    {
        [UIView animateWithDuration:[self transitionDuration:transitionContext]
                         animations:^{
                             fromViewController.view.frame = [self rectForDismissedState:transitionContext];
                         }
                         completion:^(BOOL finished)
         {
             [transitionContext completeTransition:YES];
             [fromViewController.view removeFromSuperview];
         }
         ];
    }
}

我的问题很简单。为什么我的UIVC会被呈现两次?

我本可以使用黑客,但我不知道为什么会发生这种情况。到目前为止,似乎当动画进入完成BLOCK时,它再次调用视图。

苹果医生说:

  

动画序列结束时要执行的块对象。这个   block没有返回值,并且只接受一个布尔参数   表示动画是否真正在之前完成   完成处理程序被调用。如果动画的持续时间为0,   该块在下一个运行循环周期的开始执行。   此参数可能为NULL。

自下次运行循环周期开始以来是否再次绘制视图? 注意:即使视图被呈现两次,viewDidLoad方法也只被调用一次。

我想知道为什么会这样。有一些stackoverflow问题具有相同的代码但具有相同问题的不同使用方案没有工作解决方案或解释。

感谢您的任何建议/评论。

1 个答案:

答案 0 :(得分:0)

iOS 8.0,Xcode 6.0.1,启用了ARC

是的,你用“链式动画”定义它(参见O.P.的评论)。

我目睹了一个类似的问题,试图在我的应用程序中为各种UIViewControllers隐藏和显示UIStatusBar,例如我有一个虚拟的加载后屏幕UIViewController,它显示与加载屏幕相同的图像,但它有一些添加的动画。

我正在使用自定义转换,其中包含一个UIViewController,它通过向自身添加或删除视图并将“to”UIViewController“控件”分配给自身来处理从“from”UIViewController和“to”UIViewController的转换。 。等等。

在应用程序中。委托,

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;

我必须实例化“初始视图控制器”,然后用它初始化转换UIViewController。由于没有“to”UIViewControllers,转换UIViewController必须保存UIViewController的初始UIView,它被初始化,直到触发转换为止。

这是利用,

完成的
self.window.rootViewController = self.transitionViewController;
[self.window makeKeyAndVisible];

在第一次转换之后,总会有两个UIViews叠加在一起。还有两个UIViewControllers,它们作为转换期间分配的转换UIViewController的当前控件,以及在转换完成之前保留的前一个UIViewController。

这是我试图用来显示/隐藏UIStatusBar的代码,必须在* -Info.plist文件中将“基于View控制器的状态栏外观”设置为“YES”。

- (void)viewDidLoad
{
    [self performSelector:@selector(setNeedsStatusBarAppearanceUpdate)];
}

- (BOOL)prefersStatusBarHidden
{
    return false;
}

每当“返回”值从默认值“false”变为“true”时,无论何时

[self performSelector:@selector(setNeedsStatusBarAppearanceUpdate)];

被触发,延迟,没有延迟,有条件等; UIViewControllers,“to”和“from”都被重新加载。起初,这并不明显,但是在 - (void)ViewDidLoad中触发的UIViewControllers之一中实现NSURLSession之后;问题很明显。会话执行了两次,所涉及的图形内容也得到了更新。

我以两种方式成功地解决了这个问题,但是我保持了第二名。

  1. 我把所有东西都放进去 - (无效)ViewDidLoad;在if语句中,使用实例变量boolean强制它只执行一次。 - (void)ViewDidLoad;仍然加载两次,然而,我不想执行两次的事情没有。
  2. 我转换到UIViewController,UIVtatusBar隐藏状态需要在不使用我的过渡UIViewController的情况下进行更改。显示或隐藏UIStatusBar后,我会重置应用程序的“rootViewController”。委托,再次将过渡UIViewController分配为“显示”。
  3. 我在以下帖子中描述了如何执行此操作:https://stackoverflow.com/a/26403108/4018041

    感谢。希望这有助于某人。请评论OP或我自己将来如何处理这个问题。