为啥我的 UIViewController 被加载了两次? IOS 7

Posted

技术标签:

【中文标题】为啥我的 UIViewController 被加载了两次? IOS 7【英文标题】:Why is my UIViewController being loaded twice? iOS7为什么我的 UIViewController 被加载了两次? IOS 7 【发布时间】:2014-09-09 07:59:56 【问题描述】:

我正在展示我的自定义 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 出现两次?

我尝试让我的自定义 UIVC 成为延迟加载的属性,但我的应用程序崩溃说 UIVC = nil 无法以模态方式呈现。

我已经尝试过这个解决方案,但它不适用于我的问题:viewWillAppear being called twice in ios5

我也在没有帮助的情况下这样做了:Calling presentModalViewController twice?

我本可以使用 hack,但我不知道为什么会这样。到目前为止,似乎当动画进入完成BLOCK时,它再次调用了视图。

苹果文档说:

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

自从下一个运行循环周期开始后,视图是否再次被绘制? 注意:即使视图显示了两次,viewDidLoad 方法也只被调用了一次。

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

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

【问题讨论】:

嘿,刚刚签到!你有没有找到解决这个问题的方法?我刚刚结束了与类似问题的 4 天斗争。您发布的代码是“......这是解决方案”的实际代码解决了您的问题吗? 是的,该代码在 iOS7 中运行良好,但在 iOS8 中却没有。当自定义转换发生时,像不工作的代码示例这样的链接动画似乎会产生问题。我认为这是因为大多数人使用的自定义转换代码示例。那里的景色出现了两次。对两者都有效的解决方案是在 viewDidLoad 中添加 SKView,因为它只加载一次。这最终对我有用。 @banana_developer_4_iDrioid,感谢您如此迅速地澄清!我很高兴听到你找到了解决办法,最好深入挖掘并找出确切的罪魁祸首......我会发布我的情况,也许其他人可以将两者联系在一起...... 【参考方案1】:

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];

在第一次转换之后,总是有两个 UIView 相互重叠。还有两个 UIViewController,一个作为在转换期间分配的转换 UIViewController 的当前控件和在转换完成之前保留的前一个 UIViewController 存在。

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

- (void)viewDidLoad

    [self performSelector:@selector(setNeedsStatusBarAppearanceUpdate)];


- (BOOL)prefersStatusBarHidden

    return false;

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

[self performSelector:@selector(setNeedsStatusBarAppearanceUpdate)];

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

我通过两种方式成功解决了这个问题,但我保留了第二种方式。

    我把所有东西都放在 -(void)ViewDidLoad;在 if 语句中,并使用实例变量 boolean 强制它只执行一次。 -(void)ViewDidLoad;仍然加载了两次,但是,我不想执行两次的事情没有。 我转换到 UIViewController,在此 UIStatusBar 隐藏状态需要更改,而无需使用我的转换 UIViewController。显示或隐藏 UIStatusBar 后,我将重置应用程序的“rootViewController”。委托,再次像“显示”一样分配过渡 UIViewController。

我在下面的帖子中描述了如何做到这一点:https://***.com/a/26403108/4018041

谢谢。希望这可以帮助某人。请评论未来如何为 OP 或我自己处理此问题。

【讨论】:

以上是关于为啥我的 UIViewController 被加载了两次? IOS 7的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的第二个视图在转换后没有加载?

为啥我的 UIViewController 不在其视图的响应者链中?

为啥我的 UIViewController 失去了对打开模式 ViewController 的引用?

为啥我的文件没有被加载?

我的 UIImageView 中的约束有啥问题,为啥我无法在 UIViewController 上拉伸图像?

为啥来自 customTableViewCell 的 UiTextField 没有在我的 UiViewController 中使用 UITableView 返回字符串